+++ /dev/null
----
-Language: Cpp
-BasedOnStyle: Google
-PointerAlignment: Left
-...
+++ /dev/null
----
-name: Bug report
-about: Create a report to help us improve
-title: "[BUG]"
-labels: ''
-assignees: ''
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**System**
-Which OS, compiler, and compiler version are you using:
- - OS:
- - Compiler and version:
-
-**To reproduce**
-Steps to reproduce the behavior:
-1. sync to commit ...
-2. cmake/bazel...
-3. make ...
-4. See error
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
-
-**Additional context**
-Add any other context about the problem here.
+++ /dev/null
----
-name: Feature request
-about: Suggest an idea for this project
-title: "[FR]"
-labels: ''
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
+++ /dev/null
-*.a
-*.so
-*.so.?*
-*.dll
-*.exe
-*.dylib
-*.cmake
-!/cmake/*.cmake
-!/test/AssemblyTests.cmake
-*~
-*.swp
-*.pyc
-__pycache__
-
-# lcov
-*.lcov
-/lcov
-
-# cmake files.
-/Testing
-CMakeCache.txt
-CMakeFiles/
-cmake_install.cmake
-
-# makefiles.
-Makefile
-
-# in-source build.
-bin/
-lib/
-/test/*_test
-
-# exuberant ctags.
-tags
-
-# YouCompleteMe configuration.
-.ycm_extra_conf.pyc
-
-# ninja generated files.
-.ninja_deps
-.ninja_log
-build.ninja
-install_manifest.txt
-rules.ninja
-
-# bazel output symlinks.
-bazel-*
-
-# out-of-source build top-level folders.
-build/
-_build/
-build*/
-
-# in-source dependencies
-/googletest/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-CMakeSettings.json
-
-# Visual Studio Code cache/options directory
-.vscode/
+++ /dev/null
-#!/usr/bin/env bash
-
-# Install a newer CMake version
-curl -sSL https://cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.sh -o install-cmake.sh
-chmod +x install-cmake.sh
-sudo ./install-cmake.sh --prefix=/usr/local --skip-license
-
-# Checkout LLVM sources
-git clone --depth=1 https://github.com/llvm-mirror/llvm.git llvm-source
-git clone --depth=1 https://github.com/llvm-mirror/libcxx.git llvm-source/projects/libcxx
-git clone --depth=1 https://github.com/llvm-mirror/libcxxabi.git llvm-source/projects/libcxxabi
-
-# Setup libc++ options
-if [ -z "$BUILD_32_BITS" ]; then
- export BUILD_32_BITS=OFF && echo disabling 32 bit build
-fi
-
-# Build and install libc++ (Use unstable ABI for better sanitizer coverage)
-mkdir llvm-build && cd llvm-build
-cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} \
- -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/usr \
- -DLIBCXX_ABI_UNSTABLE=ON \
- -DLLVM_USE_SANITIZER=${LIBCXX_SANITIZER} \
- -DLLVM_BUILD_32_BITS=${BUILD_32_BITS} \
- ../llvm-source
-make cxx -j2
-sudo make install-cxxabi install-cxx
-cd ../
+++ /dev/null
-sudo: required
-dist: trusty
-language: cpp
-
-matrix:
- include:
- - compiler: gcc
- addons:
- apt:
- packages:
- - lcov
- env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Coverage
- - compiler: gcc
- env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Debug
- - compiler: gcc
- env: COMPILER=g++ C_COMPILER=gcc BUILD_TYPE=Release
- - compiler: gcc
- addons:
- apt:
- packages:
- - g++-multilib
- - libc6:i386
- env:
- - COMPILER=g++
- - C_COMPILER=gcc
- - BUILD_TYPE=Debug
- - BUILD_32_BITS=ON
- - EXTRA_FLAGS="-m32"
- - compiler: gcc
- addons:
- apt:
- packages:
- - g++-multilib
- - libc6:i386
- env:
- - COMPILER=g++
- - C_COMPILER=gcc
- - BUILD_TYPE=Release
- - BUILD_32_BITS=ON
- - EXTRA_FLAGS="-m32"
- - compiler: gcc
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=g++-6 C_COMPILER=gcc-6 BUILD_TYPE=Debug
- - ENABLE_SANITIZER=1
- - EXTRA_FLAGS="-fno-omit-frame-pointer -g -O2 -fsanitize=undefined,address -fuse-ld=gold"
- - compiler: clang
- env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Debug
- - compiler: clang
- env: COMPILER=clang++ C_COMPILER=clang BUILD_TYPE=Release
- # Clang w/ libc++
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- clang-3.8
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
- - LIBCXX_BUILD=1
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- clang-3.8
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release
- - LIBCXX_BUILD=1
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- # Clang w/ 32bit libc++
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- - clang-3.8
- - g++-multilib
- - libc6:i386
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
- - LIBCXX_BUILD=1
- - BUILD_32_BITS=ON
- - EXTRA_FLAGS="-m32"
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- # Clang w/ 32bit libc++
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- - clang-3.8
- - g++-multilib
- - libc6:i386
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Release
- - LIBCXX_BUILD=1
- - BUILD_32_BITS=ON
- - EXTRA_FLAGS="-m32"
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- # Clang w/ libc++, ASAN, UBSAN
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- clang-3.8
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
- - LIBCXX_BUILD=1 LIBCXX_SANITIZER="Undefined;Address"
- - ENABLE_SANITIZER=1
- - EXTRA_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=undefined,address -fno-sanitize-recover=all"
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- - UBSAN_OPTIONS=print_stacktrace=1
- # Clang w/ libc++ and MSAN
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- clang-3.8
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=Debug
- - LIBCXX_BUILD=1 LIBCXX_SANITIZER=MemoryWithOrigins
- - ENABLE_SANITIZER=1
- - EXTRA_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=memory -fsanitize-memory-track-origins"
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- # Clang w/ libc++ and MSAN
- - compiler: clang
- dist: xenial
- addons:
- apt:
- packages:
- clang-3.8
- env:
- - INSTALL_GCC6_FROM_PPA=1
- - COMPILER=clang++-3.8 C_COMPILER=clang-3.8 BUILD_TYPE=RelWithDebInfo
- - LIBCXX_BUILD=1 LIBCXX_SANITIZER=Thread
- - ENABLE_SANITIZER=1
- - EXTRA_FLAGS="-g -O2 -fno-omit-frame-pointer -fsanitize=thread -fno-sanitize-recover=all"
- - EXTRA_CXX_FLAGS="-stdlib=libc++"
- - os: osx
- osx_image: xcode8.3
- compiler: clang
- env:
- - COMPILER=clang++ BUILD_TYPE=Debug
- - os: osx
- osx_image: xcode8.3
- compiler: clang
- env:
- - COMPILER=clang++ BUILD_TYPE=Release
- - os: osx
- osx_image: xcode8.3
- compiler: clang
- env:
- - COMPILER=clang++
- - BUILD_TYPE=Release
- - BUILD_32_BITS=ON
- - EXTRA_FLAGS="-m32"
- - os: osx
- osx_image: xcode9.4
- compiler: gcc
- env:
- - COMPILER=g++-7 C_COMPILER=gcc-7 BUILD_TYPE=Debug
-
-before_script:
- - if [ -n "${LIBCXX_BUILD}" ]; then
- source .travis-libcxx-setup.sh;
- fi
- - if [ -n "${ENABLE_SANITIZER}" ]; then
- export EXTRA_OPTIONS="-DBENCHMARK_ENABLE_ASSEMBLY_TESTS=OFF";
- else
- export EXTRA_OPTIONS="";
- fi
- - mkdir -p build && cd build
-
-before_install:
- - if [ -z "$BUILD_32_BITS" ]; then
- export BUILD_32_BITS=OFF && echo disabling 32 bit build;
- fi
- - if [ -n "${INSTALL_GCC6_FROM_PPA}" ]; then
- sudo add-apt-repository -y "ppa:ubuntu-toolchain-r/test";
- sudo apt-get update --option Acquire::Retries=100 --option Acquire::http::Timeout="60";
- fi
-
-install:
- - if [ -n "${INSTALL_GCC6_FROM_PPA}" ]; then
- travis_wait sudo -E apt-get -yq --no-install-suggests --no-install-recommends install g++-6;
- fi
- - if [ "${TRAVIS_OS_NAME}" == "linux" -a "${BUILD_32_BITS}" == "OFF" ]; then
- travis_wait sudo -E apt-get -y --no-install-suggests --no-install-recommends install llvm-3.9-tools;
- sudo cp /usr/lib/llvm-3.9/bin/FileCheck /usr/local/bin/;
- fi
- - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then
- PATH=~/.local/bin:${PATH};
- pip install --user --upgrade pip;
- travis_wait pip install --user cpp-coveralls;
- fi
- - if [ "${C_COMPILER}" == "gcc-7" -a "${TRAVIS_OS_NAME}" == "osx" ]; then
- rm -f /usr/local/include/c++;
- brew update;
- travis_wait brew install gcc@7;
- fi
- - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
- sudo apt-get update -qq;
- sudo apt-get install -qq unzip cmake3;
- wget https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-linux-x86_64.sh --output-document bazel-installer.sh;
- travis_wait sudo bash bazel-installer.sh;
- fi
- - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
- curl -L -o bazel-installer.sh https://github.com/bazelbuild/bazel/releases/download/0.10.1/bazel-0.10.1-installer-darwin-x86_64.sh;
- travis_wait sudo bash bazel-installer.sh;
- fi
-
-script:
- - cmake -DCMAKE_C_COMPILER=${C_COMPILER} -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_C_FLAGS="${EXTRA_FLAGS}" -DCMAKE_CXX_FLAGS="${EXTRA_FLAGS} ${EXTRA_CXX_FLAGS}" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON -DBENCHMARK_BUILD_32_BITS=${BUILD_32_BITS} ${EXTRA_OPTIONS} ..
- - make
- - ctest -C ${BUILD_TYPE} --output-on-failure
- - bazel test -c dbg --define google_benchmark.have_regex=posix --announce_rc --verbose_failures --test_output=errors --keep_going //test/...
-
-after_success:
- - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then
- coveralls --include src --include include --gcov-options '\-lp' --root .. --build-root .;
- fi
+++ /dev/null
-import os
-import ycm_core
-
-# These are the compilation flags that will be used in case there's no
-# compilation database set (by default, one is not set).
-# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
-flags = [
-'-Wall',
-'-Werror',
-'-pedantic-errors',
-'-std=c++0x',
-'-fno-strict-aliasing',
-'-O3',
-'-DNDEBUG',
-# ...and the same thing goes for the magic -x option which specifies the
-# language that the files to be compiled are written in. This is mostly
-# relevant for c++ headers.
-# For a C project, you would set this to 'c' instead of 'c++'.
-'-x', 'c++',
-'-I', 'include',
-'-isystem', '/usr/include',
-'-isystem', '/usr/local/include',
-]
-
-
-# Set this to the absolute path to the folder (NOT the file!) containing the
-# compile_commands.json file to use that instead of 'flags'. See here for
-# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
-#
-# Most projects will NOT need to set this to anything; you can just change the
-# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
-compilation_database_folder = ''
-
-if os.path.exists( compilation_database_folder ):
- database = ycm_core.CompilationDatabase( compilation_database_folder )
-else:
- database = None
-
-SOURCE_EXTENSIONS = [ '.cc' ]
-
-def DirectoryOfThisScript():
- return os.path.dirname( os.path.abspath( __file__ ) )
-
-
-def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
- if not working_directory:
- return list( flags )
- new_flags = []
- make_next_absolute = False
- path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
- for flag in flags:
- new_flag = flag
-
- if make_next_absolute:
- make_next_absolute = False
- if not flag.startswith( '/' ):
- new_flag = os.path.join( working_directory, flag )
-
- for path_flag in path_flags:
- if flag == path_flag:
- make_next_absolute = True
- break
-
- if flag.startswith( path_flag ):
- path = flag[ len( path_flag ): ]
- new_flag = path_flag + os.path.join( working_directory, path )
- break
-
- if new_flag:
- new_flags.append( new_flag )
- return new_flags
-
-
-def IsHeaderFile( filename ):
- extension = os.path.splitext( filename )[ 1 ]
- return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
-
-
-def GetCompilationInfoForFile( filename ):
- # The compilation_commands.json file generated by CMake does not have entries
- # for header files. So we do our best by asking the db for flags for a
- # corresponding source file, if any. If one exists, the flags for that file
- # should be good enough.
- if IsHeaderFile( filename ):
- basename = os.path.splitext( filename )[ 0 ]
- for extension in SOURCE_EXTENSIONS:
- replacement_file = basename + extension
- if os.path.exists( replacement_file ):
- compilation_info = database.GetCompilationInfoForFile(
- replacement_file )
- if compilation_info.compiler_flags_:
- return compilation_info
- return None
- return database.GetCompilationInfoForFile( filename )
-
-
-def FlagsForFile( filename, **kwargs ):
- if database:
- # Bear in mind that compilation_info.compiler_flags_ does NOT return a
- # python list, but a "list-like" StringVec object
- compilation_info = GetCompilationInfoForFile( filename )
- if not compilation_info:
- return None
-
- final_flags = MakeRelativePathsInFlagsAbsolute(
- compilation_info.compiler_flags_,
- compilation_info.compiler_working_dir_ )
- else:
- relative_to = DirectoryOfThisScript()
- final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
-
- return {
- 'flags': final_flags,
- 'do_cache': True
- }
+++ /dev/null
-# This is the official list of benchmark authors for copyright purposes.
-# This file is distinct from the CONTRIBUTORS files.
-# See the latter for an explanation.
-#
-# Names should be added to this file as:
-# Name or Organization <email address>
-# The email address is not required for organizations.
-#
-# Please keep the list sorted.
-
-Albert Pretorius <pretoalb@gmail.com>
-Alex Steele <steeleal123@gmail.com>
-Andriy Berestovskyy <berestovskyy@gmail.com>
-Arne Beer <arne@twobeer.de>
-Carto
-Christopher Seymour <chris.j.seymour@hotmail.com>
-Colin Braley <braley.colin@gmail.com>
-Daniel Harvey <danielharvey458@gmail.com>
-David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
-Deniz Evrenci <denizevrenci@gmail.com>
-Dirac Research
-Dominik Czarnota <dominik.b.czarnota@gmail.com>
-Eric Backus <eric_backus@alum.mit.edu>
-Eric Fiselier <eric@efcs.ca>
-Eugene Zhuk <eugene.zhuk@gmail.com>
-Evgeny Safronov <division494@gmail.com>
-Federico Ficarelli <federico.ficarelli@gmail.com>
-Felix Homann <linuxaudio@showlabor.de>
-Gergő Szitár <szitar.gergo@gmail.com>
-Google Inc.
-International Business Machines Corporation
-Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
-Jern-Kuan Leong <jernkuan@gmail.com>
-JianXiong Zhou <zhoujianxiong2@gmail.com>
-Joao Paulo Magalhaes <joaoppmagalhaes@gmail.com>
-Jordan Williams <jwillikers@protonmail.com>
-Jussi Knuuttila <jussi.knuuttila@gmail.com>
-Kaito Udagawa <umireon@gmail.com>
-Kishan Kumar <kumar.kishan@outlook.com>
-Lei Xu <eddyxu@gmail.com>
-Matt Clarkson <mattyclarkson@gmail.com>
-Maxim Vafin <maxvafin@gmail.com>
-MongoDB Inc.
-Nick Hutchinson <nshutchinson@gmail.com>
-Oleksandr Sochka <sasha.sochka@gmail.com>
-Ori Livneh <ori.livneh@gmail.com>
-Paul Redmond <paul.redmond@gmail.com>
-Radoslav Yovchev <radoslav.tm@gmail.com>
-Roman Lebedev <lebedev.ri@gmail.com>
-Sayan Bhattacharjee <aero.sayan@gmail.com>
-Shuo Chen <chenshuo@chenshuo.com>
-Steinar H. Gunderson <sgunderson@bigfoot.com>
-Stripe, Inc.
-Yixuan Qiu <yixuanq@gmail.com>
-Yusuke Suzuki <utatane.tea@gmail.com>
-Zbigniew Skowron <zbychs@gmail.com>
+++ /dev/null
-licenses(["notice"])
-
-config_setting(
- name = "windows",
- values = {
- "cpu": "x64_windows",
- },
- visibility = [":__subpackages__"],
-)
-
-load("@rules_cc//cc:defs.bzl", "cc_library")
-
-cc_library(
- name = "benchmark",
- srcs = glob(
- [
- "src/*.cc",
- "src/*.h",
- ],
- exclude = ["src/benchmark_main.cc"],
- ),
- hdrs = ["include/benchmark/benchmark.h"],
- linkopts = select({
- ":windows": ["-DEFAULTLIB:shlwapi.lib"],
- "//conditions:default": ["-pthread"],
- }),
- strip_include_prefix = "include",
- visibility = ["//visibility:public"],
-)
-
-cc_library(
- name = "benchmark_main",
- srcs = ["src/benchmark_main.cc"],
- hdrs = ["include/benchmark/benchmark.h"],
- strip_include_prefix = "include",
- visibility = ["//visibility:public"],
- deps = [":benchmark"],
-)
-
-cc_library(
- name = "benchmark_internal_headers",
- hdrs = glob(["src/*.h"]),
- visibility = ["//test:__pkg__"],
-)
+++ /dev/null
-cmake_minimum_required (VERSION 3.5.1)
-
-foreach(p
- CMP0048 # OK to clear PROJECT_VERSION on project()
- CMP0054 # CMake 3.1
- CMP0056 # export EXE_LINKER_FLAGS to try_run
- CMP0057 # Support no if() IN_LIST operator
- CMP0063 # Honor visibility properties for all targets
- CMP0077 # Allow option() overrides in importing projects
- )
- if(POLICY ${p})
- cmake_policy(SET ${p} NEW)
- endif()
-endforeach()
-
-project (benchmark CXX)
-
-option(BENCHMARK_ENABLE_TESTING "Enable testing of the benchmark library." OFF)
-option(BENCHMARK_ENABLE_EXCEPTIONS "Enable the use of exceptions in the benchmark library." ON)
-option(BENCHMARK_ENABLE_LTO "Enable link time optimisation of the benchmark library." OFF)
-option(BENCHMARK_USE_LIBCXX "Build and test using libc++ as the standard library." OFF)
-if(NOT MSVC)
- option(BENCHMARK_BUILD_32_BITS "Build a 32 bit version of the library." OFF)
-else()
- set(BENCHMARK_BUILD_32_BITS OFF CACHE BOOL "Build a 32 bit version of the library - unsupported when using MSVC)" FORCE)
-endif()
-option(BENCHMARK_ENABLE_INSTALL "Enable installation of benchmark. (Projects embedding benchmark may want to turn this OFF.)" ON)
-
-# Allow unmet dependencies to be met using CMake's ExternalProject mechanics, which
-# may require downloading the source code.
-option(BENCHMARK_DOWNLOAD_DEPENDENCIES "Allow the downloading and in-tree building of unmet dependencies" OFF)
-
-# This option can be used to disable building and running unit tests which depend on gtest
-# in cases where it is not possible to build or find a valid version of gtest.
-option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend on gtest" ON)
-
-set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
-set(ENABLE_ASSEMBLY_TESTS_DEFAULT OFF)
-function(should_enable_assembly_tests)
- if(CMAKE_BUILD_TYPE)
- string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
- if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage")
- # FIXME: The --coverage flag needs to be removed when building assembly
- # tests for this to work.
- return()
- endif()
- endif()
- if (MSVC)
- return()
- elseif(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
- return()
- elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
- # FIXME: Make these work on 32 bit builds
- return()
- elseif(BENCHMARK_BUILD_32_BITS)
- # FIXME: Make these work on 32 bit builds
- return()
- endif()
- find_program(LLVM_FILECHECK_EXE FileCheck)
- if (LLVM_FILECHECK_EXE)
- set(LLVM_FILECHECK_EXE "${LLVM_FILECHECK_EXE}" CACHE PATH "llvm filecheck" FORCE)
- message(STATUS "LLVM FileCheck Found: ${LLVM_FILECHECK_EXE}")
- else()
- message(STATUS "Failed to find LLVM FileCheck")
- return()
- endif()
- set(ENABLE_ASSEMBLY_TESTS_DEFAULT ON PARENT_SCOPE)
-endfunction()
-should_enable_assembly_tests()
-
-# This option disables the building and running of the assembly verification tests
-option(BENCHMARK_ENABLE_ASSEMBLY_TESTS "Enable building and running the assembly tests"
- ${ENABLE_ASSEMBLY_TESTS_DEFAULT})
-
-# Make sure we can import out CMake functions
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
-
-
-# Read the git tags to determine the project version
-include(GetGitVersion)
-get_git_version(GIT_VERSION)
-
-# Tell the user what versions we are using
-string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" VERSION ${GIT_VERSION})
-message(STATUS "Version: ${VERSION}")
-
-# The version of the libraries
-set(GENERIC_LIB_VERSION ${VERSION})
-string(SUBSTRING ${VERSION} 0 1 GENERIC_LIB_SOVERSION)
-
-# Import our CMake modules
-include(CheckCXXCompilerFlag)
-include(AddCXXCompilerFlag)
-include(CXXFeatureCheck)
-
-if (BENCHMARK_BUILD_32_BITS)
- add_required_cxx_compiler_flag(-m32)
-endif()
-
-if (MSVC)
- # Turn compiler warnings up to 11
- string(REGEX REPLACE "[-/]W[1-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
- add_definitions(-D_CRT_SECURE_NO_WARNINGS)
-
- if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
- add_cxx_compiler_flag(-EHs-)
- add_cxx_compiler_flag(-EHa-)
- add_definitions(-D_HAS_EXCEPTIONS=0)
- endif()
- # Link time optimisation
- if (BENCHMARK_ENABLE_LTO)
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
- set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG")
- set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
- set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
-
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /GL")
- string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO}")
- set(CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
- string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}")
- set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
- string(REGEX REPLACE "[-/]INCREMENTAL" "/INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")
- set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /LTCG")
-
- set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /GL")
- set(CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL "${CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL} /LTCG")
- set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} /LTCG")
- set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /LTCG")
- endif()
-else()
- # Try and enable C++11. Don't use C++14 because it doesn't work in some
- # configurations.
- add_cxx_compiler_flag(-std=c++11)
- if (NOT HAVE_CXX_FLAG_STD_CXX11)
- add_cxx_compiler_flag(-std=c++0x)
- endif()
-
- # Turn compiler warnings up to 11
- add_cxx_compiler_flag(-Wall)
- add_cxx_compiler_flag(-Wextra)
- add_cxx_compiler_flag(-Wshadow)
- add_cxx_compiler_flag(-Werror RELEASE)
- add_cxx_compiler_flag(-Werror RELWITHDEBINFO)
- add_cxx_compiler_flag(-Werror MINSIZEREL)
- # Disabled until googletest (gmock) stops emitting variadic macro warnings
- #add_cxx_compiler_flag(-pedantic)
- #add_cxx_compiler_flag(-pedantic-errors)
- add_cxx_compiler_flag(-Wshorten-64-to-32)
- add_cxx_compiler_flag(-fstrict-aliasing)
- # Disable warnings regarding deprecated parts of the library while building
- # and testing those parts of the library.
- add_cxx_compiler_flag(-Wno-deprecated-declarations)
- if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
- # Intel silently ignores '-Wno-deprecated-declarations',
- # warning no. 1786 must be explicitly disabled.
- # See #631 for rationale.
- add_cxx_compiler_flag(-wd1786)
- endif()
- # Disable deprecation warnings for release builds (when -Werror is enabled).
- add_cxx_compiler_flag(-Wno-deprecated RELEASE)
- add_cxx_compiler_flag(-Wno-deprecated RELWITHDEBINFO)
- add_cxx_compiler_flag(-Wno-deprecated MINSIZEREL)
- if (NOT BENCHMARK_ENABLE_EXCEPTIONS)
- add_cxx_compiler_flag(-fno-exceptions)
- endif()
-
- if (HAVE_CXX_FLAG_FSTRICT_ALIASING)
- if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Intel") #ICC17u2: Many false positives for Wstrict-aliasing
- add_cxx_compiler_flag(-Wstrict-aliasing)
- endif()
- endif()
- # ICC17u2: overloaded virtual function "benchmark::Fixture::SetUp" is only partially overridden
- # (because of deprecated overload)
- add_cxx_compiler_flag(-wd654)
- add_cxx_compiler_flag(-Wthread-safety)
- if (HAVE_CXX_FLAG_WTHREAD_SAFETY)
- cxx_feature_check(THREAD_SAFETY_ATTRIBUTES)
- endif()
-
- # On most UNIX like platforms g++ and clang++ define _GNU_SOURCE as a
- # predefined macro, which turns on all of the wonderful libc extensions.
- # However g++ doesn't do this in Cygwin so we have to define it ourselfs
- # since we depend on GNU/POSIX/BSD extensions.
- if (CYGWIN)
- add_definitions(-D_GNU_SOURCE=1)
- endif()
-
- if (QNXNTO)
- add_definitions(-D_QNX_SOURCE)
- endif()
-
- # Link time optimisation
- if (BENCHMARK_ENABLE_LTO)
- add_cxx_compiler_flag(-flto)
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- find_program(GCC_AR gcc-ar)
- if (GCC_AR)
- set(CMAKE_AR ${GCC_AR})
- endif()
- find_program(GCC_RANLIB gcc-ranlib)
- if (GCC_RANLIB)
- set(CMAKE_RANLIB ${GCC_RANLIB})
- endif()
- elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- include(llvm-toolchain)
- endif()
- endif()
-
- # Coverage build type
- set(BENCHMARK_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG}"
- CACHE STRING "Flags used by the C++ compiler during coverage builds."
- FORCE)
- set(BENCHMARK_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_DEBUG}"
- CACHE STRING "Flags used for linking binaries during coverage builds."
- FORCE)
- set(BENCHMARK_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}"
- CACHE STRING "Flags used by the shared libraries linker during coverage builds."
- FORCE)
- mark_as_advanced(
- BENCHMARK_CXX_FLAGS_COVERAGE
- BENCHMARK_EXE_LINKER_FLAGS_COVERAGE
- BENCHMARK_SHARED_LINKER_FLAGS_COVERAGE)
- set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
- "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
- add_cxx_compiler_flag(--coverage COVERAGE)
-endif()
-
-if (BENCHMARK_USE_LIBCXX)
- if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- add_cxx_compiler_flag(-stdlib=libc++)
- elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
- "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
- add_cxx_compiler_flag(-nostdinc++)
- message(WARNING "libc++ header path must be manually specified using CMAKE_CXX_FLAGS")
- # Adding -nodefaultlibs directly to CMAKE_<TYPE>_LINKER_FLAGS will break
- # configuration checks such as 'find_package(Threads)'
- list(APPEND BENCHMARK_CXX_LINKER_FLAGS -nodefaultlibs)
- # -lc++ cannot be added directly to CMAKE_<TYPE>_LINKER_FLAGS because
- # linker flags appear before all linker inputs and -lc++ must appear after.
- list(APPEND BENCHMARK_CXX_LIBRARIES c++)
- else()
- message(FATAL_ERROR "-DBENCHMARK_USE_LIBCXX:BOOL=ON is not supported for compiler")
- endif()
-endif(BENCHMARK_USE_LIBCXX)
-
-# C++ feature checks
-# Determine the correct regular expression engine to use
-cxx_feature_check(STD_REGEX)
-cxx_feature_check(GNU_POSIX_REGEX)
-cxx_feature_check(POSIX_REGEX)
-if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
- message(FATAL_ERROR "Failed to determine the source files for the regular expression backend")
-endif()
-if (NOT BENCHMARK_ENABLE_EXCEPTIONS AND HAVE_STD_REGEX
- AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX)
- message(WARNING "Using std::regex with exceptions disabled is not fully supported")
-endif()
-cxx_feature_check(STEADY_CLOCK)
-# Ensure we have pthreads
-set(THREADS_PREFER_PTHREAD_FLAG ON)
-find_package(Threads REQUIRED)
-
-# Set up directories
-include_directories(${PROJECT_SOURCE_DIR}/include)
-
-# Build the targets
-add_subdirectory(src)
-
-if (BENCHMARK_ENABLE_TESTING)
- enable_testing()
- if (BENCHMARK_ENABLE_GTEST_TESTS AND
- NOT (TARGET gtest AND TARGET gtest_main AND
- TARGET gmock AND TARGET gmock_main))
- include(GoogleTest)
- endif()
- add_subdirectory(test)
-endif()
+++ /dev/null
-# How to contribute #
-
-We'd love to accept your patches and contributions to this project. There are
-a just a few small guidelines you need to follow.
-
-
-## Contributor License Agreement ##
-
-Contributions to any Google project must be accompanied by a Contributor
-License Agreement. This is not a copyright **assignment**, it simply gives
-Google permission to use and redistribute your contributions as part of the
-project.
-
- * If you are an individual writing original source code and you're sure you
- own the intellectual property, then you'll need to sign an [individual
- CLA][].
-
- * If you work for a company that wants to allow you to contribute your work,
- then you'll need to sign a [corporate CLA][].
-
-You generally only need to submit a CLA once, so if you've already submitted
-one (even if it was for a different project), you probably don't need to do it
-again.
-
-[individual CLA]: https://developers.google.com/open-source/cla/individual
-[corporate CLA]: https://developers.google.com/open-source/cla/corporate
-
-Once your CLA is submitted (or if you already submitted one for
-another Google project), make a commit adding yourself to the
-[AUTHORS][] and [CONTRIBUTORS][] files. This commit can be part
-of your first [pull request][].
-
-[AUTHORS]: AUTHORS
-[CONTRIBUTORS]: CONTRIBUTORS
-
-
-## Submitting a patch ##
-
- 1. It's generally best to start by opening a new issue describing the bug or
- feature you're intending to fix. Even if you think it's relatively minor,
- it's helpful to know what people are working on. Mention in the initial
- issue that you are planning to work on that bug or feature so that it can
- be assigned to you.
-
- 1. Follow the normal process of [forking][] the project, and setup a new
- branch to work in. It's important that each group of changes be done in
- separate branches in order to ensure that a pull request only includes the
- commits related to that bug or feature.
-
- 1. Do your best to have [well-formed commit messages][] for each change.
- This provides consistency throughout the project, and ensures that commit
- messages are able to be formatted properly by various git tools.
-
- 1. Finally, push the commits to your fork and submit a [pull request][].
-
-[forking]: https://help.github.com/articles/fork-a-repo
-[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
-[pull request]: https://help.github.com/articles/creating-a-pull-request
+++ /dev/null
-# People who have agreed to one of the CLAs and can contribute patches.
-# The AUTHORS file lists the copyright holders; this file
-# lists people. For example, Google employees are listed here
-# but not in AUTHORS, because Google holds the copyright.
-#
-# Names should be added to this file only after verifying that
-# the individual or the individual's organization has agreed to
-# the appropriate Contributor License Agreement, found here:
-#
-# https://developers.google.com/open-source/cla/individual
-# https://developers.google.com/open-source/cla/corporate
-#
-# The agreement for individuals can be filled out on the web.
-#
-# When adding J Random Contributor's name to this file,
-# either J's name or J's organization's name should be
-# added to the AUTHORS file, depending on whether the
-# individual or corporate CLA was used.
-#
-# Names should be added to this file as:
-# Name <email address>
-#
-# Please keep the list sorted.
-
-Albert Pretorius <pretoalb@gmail.com>
-Alex Steele <steelal123@gmail.com>
-Andriy Berestovskyy <berestovskyy@gmail.com>
-Arne Beer <arne@twobeer.de>
-Billy Robert O'Neal III <billy.oneal@gmail.com> <bion@microsoft.com>
-Chris Kennelly <ckennelly@google.com> <ckennelly@ckennelly.com>
-Christopher Seymour <chris.j.seymour@hotmail.com>
-Colin Braley <braley.colin@gmail.com>
-Cyrille Faucheux <cyrille.faucheux@gmail.com>
-Daniel Harvey <danielharvey458@gmail.com>
-David Coeurjolly <david.coeurjolly@liris.cnrs.fr>
-Deniz Evrenci <denizevrenci@gmail.com>
-Dominic Hamon <dma@stripysock.com> <dominic@google.com>
-Dominik Czarnota <dominik.b.czarnota@gmail.com>
-Eric Backus <eric_backus@alum.mit.edu>
-Eric Fiselier <eric@efcs.ca>
-Eugene Zhuk <eugene.zhuk@gmail.com>
-Evgeny Safronov <division494@gmail.com>
-Federico Ficarelli <federico.ficarelli@gmail.com>
-Felix Homann <linuxaudio@showlabor.de>
-Geoffrey Martin-Noble <gcmn@google.com> <gmngeoffrey@gmail.com>
-Gergő Szitár <szitar.gergo@gmail.com>
-Hannes Hauswedell <h2@fsfe.org>
-Ismael Jimenez Martinez <ismael.jimenez.martinez@gmail.com>
-Jern-Kuan Leong <jernkuan@gmail.com>
-JianXiong Zhou <zhoujianxiong2@gmail.com>
-Joao Paulo Magalhaes <joaoppmagalhaes@gmail.com>
-John Millikin <jmillikin@stripe.com>
-Jordan Williams <jwillikers@protonmail.com>
-Jussi Knuuttila <jussi.knuuttila@gmail.com>
-Kai Wolf <kai.wolf@gmail.com>
-Kaito Udagawa <umireon@gmail.com>
-Kishan Kumar <kumar.kishan@outlook.com>
-Lei Xu <eddyxu@gmail.com>
-Matt Clarkson <mattyclarkson@gmail.com>
-Maxim Vafin <maxvafin@gmail.com>
-Nick Hutchinson <nshutchinson@gmail.com>
-Oleksandr Sochka <sasha.sochka@gmail.com>
-Ori Livneh <ori.livneh@gmail.com>
-Pascal Leroy <phl@google.com>
-Paul Redmond <paul.redmond@gmail.com>
-Pierre Phaneuf <pphaneuf@google.com>
-Radoslav Yovchev <radoslav.tm@gmail.com>
-Raul Marin <rmrodriguez@cartodb.com>
-Ray Glover <ray.glover@uk.ibm.com>
-Robert Guo <robert.guo@mongodb.com>
-Roman Lebedev <lebedev.ri@gmail.com>
-Sayan Bhattacharjee <aero.sayan@gmail.com>
-Shuo Chen <chenshuo@chenshuo.com>
-Tobias Ulvgård <tobias.ulvgard@dirac.se>
-Tom Madams <tom.ej.madams@gmail.com> <tmadams@google.com>
-Yixuan Qiu <yixuanq@gmail.com>
-Yusuke Suzuki <utatane.tea@gmail.com>
-Zbigniew Skowron <zbychs@gmail.com>
+++ /dev/null
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+++ /dev/null
-# Benchmark
-
-[](https://travis-ci.org/google/benchmark)
-[](https://ci.appveyor.com/project/google/benchmark/branch/master)
-[](https://coveralls.io/r/google/benchmark)
-[](https://slackin-iqtfqnpzxd.now.sh/)
-
-A library to benchmark code snippets, similar to unit tests. Example:
-
-```c++
-#include <benchmark/benchmark.h>
-
-static void BM_SomeFunction(benchmark::State& state) {
- // Perform setup here
- for (auto _ : state) {
- // This code gets timed
- SomeFunction();
- }
-}
-// Register the function as a benchmark
-BENCHMARK(BM_SomeFunction);
-// Run the benchmark
-BENCHMARK_MAIN();
-```
-
-To get started, see [Requirements](#requirements) and
-[Installation](#installation). See [Usage](#usage) for a full example and the
-[User Guide](#user-guide) for a more comprehensive feature overview.
-
-It may also help to read the [Google Test documentation](https://github.com/google/googletest/blob/master/googletest/docs/primer.md)
-as some of the structural aspects of the APIs are similar.
-
-### Resources
-
-[Discussion group](https://groups.google.com/d/forum/benchmark-discuss)
-
-IRC channel: [freenode](https://freenode.net) #googlebenchmark
-
-[Additional Tooling Documentation](docs/tools.md)
-
-[Assembly Testing Documentation](docs/AssemblyTests.md)
-
-## Requirements
-
-The library can be used with C++03. However, it requires C++11 to build,
-including compiler and standard library support.
-
-The following minimum versions are required to build the library:
-
-* GCC 4.8
-* Clang 3.4
-* Visual Studio 14 2015
-* Intel 2015 Update 1
-
-See [Platform-Specific Build Instructions](#platform-specific-build-instructions).
-
-## Installation
-
-This describes the installation process using cmake. As pre-requisites, you'll
-need git and cmake installed.
-
-_See [dependencies.md](dependencies.md) for more details regarding supported
-versions of build tools._
-
-```bash
-# Check out the library.
-$ git clone https://github.com/google/benchmark.git
-# Benchmark requires Google Test as a dependency. Add the source tree as a subdirectory.
-$ git clone https://github.com/google/googletest.git benchmark/googletest
-# Go to the library root directory
-$ cd benchmark
-# Make a build directory to place the build output.
-$ mkdir build && cd build
-# Generate a Makefile with cmake.
-# Use cmake -G <generator> to generate a different file type.
-$ cmake ../
-# Build the library.
-# Use make -j<number_of_parallel_jobs> to speed up the build process, e.g. make -j8 .
-$ make
-```
-This builds the `benchmark` and `benchmark_main` libraries and tests.
-On a unix system, the build directory should now look something like this:
-
-```
-/benchmark
- /build
- /src
- /libbenchmark.a
- /libbenchmark_main.a
- /test
- ...
-```
-
-Next, you can run the tests to check the build.
-
-```bash
-$ make test
-```
-
-If you want to install the library globally, also run:
-
-```
-sudo make install
-```
-
-Note that Google Benchmark requires Google Test to build and run the tests. This
-dependency can be provided two ways:
-
-* Checkout the Google Test sources into `benchmark/googletest` as above.
-* Otherwise, if `-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON` is specified during
- configuration, the library will automatically download and build any required
- dependencies.
-
-If you do not wish to build and run the tests, add `-DBENCHMARK_ENABLE_GTEST_TESTS=OFF`
-to `CMAKE_ARGS`.
-
-### Debug vs Release
-
-By default, benchmark builds as a debug library. You will see a warning in the
-output when this is the case. To build it as a release library instead, use:
-
-```
-cmake -DCMAKE_BUILD_TYPE=Release
-```
-
-To enable link-time optimisation, use
-
-```
-cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_LTO=true
-```
-
-If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake
-cache variables, if autodetection fails.
-
-If you are using clang, you may need to set `LLVMAR_EXECUTABLE`,
-`LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables.
-
-
-### Stable and Experimental Library Versions
-
-The main branch contains the latest stable version of the benchmarking library;
-the API of which can be considered largely stable, with source breaking changes
-being made only upon the release of a new major version.
-
-Newer, experimental, features are implemented and tested on the
-[`v2` branch](https://github.com/google/benchmark/tree/v2). Users who wish
-to use, test, and provide feedback on the new features are encouraged to try
-this branch. However, this branch provides no stability guarantees and reserves
-the right to change and break the API at any time.
-
-## Usage
-
-### Basic usage
-
-Define a function that executes the code to measure, register it as a benchmark
-function using the `BENCHMARK` macro, and ensure an appropriate `main` function
-is available:
-
-```c++
-#include <benchmark/benchmark.h>
-
-static void BM_StringCreation(benchmark::State& state) {
- for (auto _ : state)
- std::string empty_string;
-}
-// Register the function as a benchmark
-BENCHMARK(BM_StringCreation);
-
-// Define another benchmark
-static void BM_StringCopy(benchmark::State& state) {
- std::string x = "hello";
- for (auto _ : state)
- std::string copy(x);
-}
-BENCHMARK(BM_StringCopy);
-
-BENCHMARK_MAIN();
-```
-
-To run the benchmark, compile and link against the `benchmark` library
-(libbenchmark.a/.so). If you followed the build steps above, this library will
-be under the build directory you created.
-
-```bash
-# Example on linux after running the build steps above. Assumes the
-# `benchmark` and `build` directories are under the current directory.
-$ g++ mybenchmark.cc -std=c++11 -isystem benchmark/include \
- -Lbenchmark/build/src -lbenchmark -lpthread -o mybenchmark
-```
-
-Alternatively, link against the `benchmark_main` library and remove
-`BENCHMARK_MAIN();` above to get the same behavior.
-
-The compiled executable will run all benchmarks by default. Pass the `--help`
-flag for option information or see the guide below.
-
-### Usage with CMake
-
-If using CMake, it is recommended to link against the project-provided
-`benchmark::benchmark` and `benchmark::benchmark_main` targets using
-`target_link_libraries`.
-It is possible to use ```find_package``` to import an installed version of the
-library.
-```cmake
-find_package(benchmark REQUIRED)
-```
-Alternatively, ```add_subdirectory``` will incorporate the library directly in
-to one's CMake project.
-```cmake
-add_subdirectory(benchmark)
-```
-Either way, link to the library as follows.
-```cmake
-target_link_libraries(MyTarget benchmark::benchmark)
-```
-
-## Platform Specific Build Instructions
-
-### Building with GCC
-
-When the library is built using GCC it is necessary to link with the pthread
-library due to how GCC implements `std::thread`. Failing to link to pthread will
-lead to runtime exceptions (unless you're using libc++), not linker errors. See
-[issue #67](https://github.com/google/benchmark/issues/67) for more details. You
-can link to pthread by adding `-pthread` to your linker command. Note, you can
-also use `-lpthread`, but there are potential issues with ordering of command
-line parameters if you use that.
-
-### Building with Visual Studio 2015 or 2017
-
-The `shlwapi` library (`-lshlwapi`) is required to support a call to `CPUInfo` which reads the registry. Either add `shlwapi.lib` under `[ Configuration Properties > Linker > Input ]`, or use the following:
-
-```
-// Alternatively, can add libraries using linker options.
-#ifdef _WIN32
-#pragma comment ( lib, "Shlwapi.lib" )
-#ifdef _DEBUG
-#pragma comment ( lib, "benchmarkd.lib" )
-#else
-#pragma comment ( lib, "benchmark.lib" )
-#endif
-#endif
-```
-
-Can also use the graphical version of CMake:
-* Open `CMake GUI`.
-* Under `Where to build the binaries`, same path as source plus `build`.
-* Under `CMAKE_INSTALL_PREFIX`, same path as source plus `install`.
-* Click `Configure`, `Generate`, `Open Project`.
-* If build fails, try deleting entire directory and starting again, or unticking options to build less.
-
-### Building with Intel 2015 Update 1 or Intel System Studio Update 4
-
-See instructions for building with Visual Studio. Once built, right click on the solution and change the build to Intel.
-
-### Building on Solaris
-
-If you're running benchmarks on solaris, you'll want the kstat library linked in
-too (`-lkstat`).
-
-## User Guide
-
-### Command Line
-
-[Output Formats](#output-formats)
-
-[Output Files](#output-files)
-
-[Running Benchmarks](#running-benchmarks)
-
-[Running a Subset of Benchmarks](#running-a-subset-of-benchmarks)
-
-[Result Comparison](#result-comparison)
-
-### Library
-
-[Runtime and Reporting Considerations](#runtime-and-reporting-considerations)
-
-[Passing Arguments](#passing-arguments)
-
-[Calculating Asymptotic Complexity](#asymptotic-complexity)
-
-[Templated Benchmarks](#templated-benchmarks)
-
-[Fixtures](#fixtures)
-
-[Custom Counters](#custom-counters)
-
-[Multithreaded Benchmarks](#multithreaded-benchmarks)
-
-[CPU Timers](#cpu-timers)
-
-[Manual Timing](#manual-timing)
-
-[Setting the Time Unit](#setting-the-time-unit)
-
-[Preventing Optimization](#preventing-optimization)
-
-[Reporting Statistics](#reporting-statistics)
-
-[Custom Statistics](#custom-statistics)
-
-[Using RegisterBenchmark](#using-register-benchmark)
-
-[Exiting with an Error](#exiting-with-an-error)
-
-[A Faster KeepRunning Loop](#a-faster-keep-running-loop)
-
-[Disabling CPU Frequency Scaling](#disabling-cpu-frequency-scaling)
-
-
-<a name="output-formats" />
-
-### Output Formats
-
-The library supports multiple output formats. Use the
-`--benchmark_format=<console|json|csv>` flag (or set the
-`BENCHMARK_FORMAT=<console|json|csv>` environment variable) to set
-the format type. `console` is the default format.
-
-The Console format is intended to be a human readable format. By default
-the format generates color output. Context is output on stderr and the
-tabular data on stdout. Example tabular output looks like:
-
-```
-Benchmark Time(ns) CPU(ns) Iterations
-----------------------------------------------------------------------
-BM_SetInsert/1024/1 28928 29349 23853 133.097kB/s 33.2742k items/s
-BM_SetInsert/1024/8 32065 32913 21375 949.487kB/s 237.372k items/s
-BM_SetInsert/1024/10 33157 33648 21431 1.13369MB/s 290.225k items/s
-```
-
-The JSON format outputs human readable json split into two top level attributes.
-The `context` attribute contains information about the run in general, including
-information about the CPU and the date.
-The `benchmarks` attribute contains a list of every benchmark run. Example json
-output looks like:
-
-```json
-{
- "context": {
- "date": "2015/03/17-18:40:25",
- "num_cpus": 40,
- "mhz_per_cpu": 2801,
- "cpu_scaling_enabled": false,
- "build_type": "debug"
- },
- "benchmarks": [
- {
- "name": "BM_SetInsert/1024/1",
- "iterations": 94877,
- "real_time": 29275,
- "cpu_time": 29836,
- "bytes_per_second": 134066,
- "items_per_second": 33516
- },
- {
- "name": "BM_SetInsert/1024/8",
- "iterations": 21609,
- "real_time": 32317,
- "cpu_time": 32429,
- "bytes_per_second": 986770,
- "items_per_second": 246693
- },
- {
- "name": "BM_SetInsert/1024/10",
- "iterations": 21393,
- "real_time": 32724,
- "cpu_time": 33355,
- "bytes_per_second": 1199226,
- "items_per_second": 299807
- }
- ]
-}
-```
-
-The CSV format outputs comma-separated values. The `context` is output on stderr
-and the CSV itself on stdout. Example CSV output looks like:
-
-```
-name,iterations,real_time,cpu_time,bytes_per_second,items_per_second,label
-"BM_SetInsert/1024/1",65465,17890.7,8407.45,475768,118942,
-"BM_SetInsert/1024/8",116606,18810.1,9766.64,3.27646e+06,819115,
-"BM_SetInsert/1024/10",106365,17238.4,8421.53,4.74973e+06,1.18743e+06,
-```
-
-<a name="output-files" />
-
-### Output Files
-
-Write benchmark results to a file with the `--benchmark_out=<filename>` option
-(or set `BENCHMARK_OUT`). Specify the output format with
-`--benchmark_out_format={json|console|csv}` (or set
-`BENCHMARK_OUT_FORMAT={json|console|csv}`). Note that specifying
-`--benchmark_out` does not suppress the console output.
-
-<a name="running-benchmarks" />
-
-### Running Benchmarks
-
-Benchmarks are executed by running the produced binaries. Benchmarks binaries,
-by default, accept options that may be specified either through their command
-line interface or by setting environment variables before execution. For every
-`--option_flag=<value>` CLI switch, a corresponding environment variable
-`OPTION_FLAG=<value>` exist and is used as default if set (CLI switches always
- prevails). A complete list of CLI options is available running benchmarks
- with the `--help` switch.
-
-<a name="running-a-subset-of-benchmarks" />
-
-### Running a Subset of Benchmarks
-
-The `--benchmark_filter=<regex>` option (or `BENCHMARK_FILTER=<regex>`
-environment variable) can be used to only run the benchmarks that match
-the specified `<regex>`. For example:
-
-```bash
-$ ./run_benchmarks.x --benchmark_filter=BM_memcpy/32
-Run on (1 X 2300 MHz CPU )
-2016-06-25 19:34:24
-Benchmark Time CPU Iterations
-----------------------------------------------------
-BM_memcpy/32 11 ns 11 ns 79545455
-BM_memcpy/32k 2181 ns 2185 ns 324074
-BM_memcpy/32 12 ns 12 ns 54687500
-BM_memcpy/32k 1834 ns 1837 ns 357143
-```
-
-<a name="result-comparison" />
-
-### Result comparison
-
-It is possible to compare the benchmarking results.
-See [Additional Tooling Documentation](docs/tools.md)
-
-<a name="runtime-and-reporting-considerations" />
-
-### Runtime and Reporting Considerations
-
-When the benchmark binary is executed, each benchmark function is run serially.
-The number of iterations to run is determined dynamically by running the
-benchmark a few times and measuring the time taken and ensuring that the
-ultimate result will be statistically stable. As such, faster benchmark
-functions will be run for more iterations than slower benchmark functions, and
-the number of iterations is thus reported.
-
-In all cases, the number of iterations for which the benchmark is run is
-governed by the amount of time the benchmark takes. Concretely, the number of
-iterations is at least one, not more than 1e9, until CPU time is greater than
-the minimum time, or the wallclock time is 5x minimum time. The minimum time is
-set per benchmark by calling `MinTime` on the registered benchmark object.
-
-Average timings are then reported over the iterations run. If multiple
-repetitions are requested using the `--benchmark_repetitions` command-line
-option, or at registration time, the benchmark function will be run several
-times and statistical results across these repetitions will also be reported.
-
-As well as the per-benchmark entries, a preamble in the report will include
-information about the machine on which the benchmarks are run.
-
-<a name="passing-arguments" />
-
-### Passing Arguments
-
-Sometimes a family of benchmarks can be implemented with just one routine that
-takes an extra argument to specify which one of the family of benchmarks to
-run. For example, the following code defines a family of benchmarks for
-measuring the speed of `memcpy()` calls of different lengths:
-
-```c++
-static void BM_memcpy(benchmark::State& state) {
- char* src = new char[state.range(0)];
- char* dst = new char[state.range(0)];
- memset(src, 'x', state.range(0));
- for (auto _ : state)
- memcpy(dst, src, state.range(0));
- state.SetBytesProcessed(int64_t(state.iterations()) *
- int64_t(state.range(0)));
- delete[] src;
- delete[] dst;
-}
-BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10);
-```
-
-The preceding code is quite repetitive, and can be replaced with the following
-short-hand. The following invocation will pick a few appropriate arguments in
-the specified range and will generate a benchmark for each such argument.
-
-```c++
-BENCHMARK(BM_memcpy)->Range(8, 8<<10);
-```
-
-By default the arguments in the range are generated in multiples of eight and
-the command above selects [ 8, 64, 512, 4k, 8k ]. In the following code the
-range multiplier is changed to multiples of two.
-
-```c++
-BENCHMARK(BM_memcpy)->RangeMultiplier(2)->Range(8, 8<<10);
-```
-
-Now arguments generated are [ 8, 16, 32, 64, 128, 256, 512, 1024, 2k, 4k, 8k ].
-
-The preceding code shows a method of defining a sparse range. The following
-example shows a method of defining a dense range. It is then used to benchmark
-the performance of `std::vector` initialization for uniformly increasing sizes.
-
-```c++
-static void BM_DenseRange(benchmark::State& state) {
- for(auto _ : state) {
- std::vector<int> v(state.range(0), state.range(0));
- benchmark::DoNotOptimize(v.data());
- benchmark::ClobberMemory();
- }
-}
-BENCHMARK(BM_DenseRange)->DenseRange(0, 1024, 128);
-```
-
-Now arguments generated are [ 0, 128, 256, 384, 512, 640, 768, 896, 1024 ].
-
-You might have a benchmark that depends on two or more inputs. For example, the
-following code defines a family of benchmarks for measuring the speed of set
-insertion.
-
-```c++
-static void BM_SetInsert(benchmark::State& state) {
- std::set<int> data;
- for (auto _ : state) {
- state.PauseTiming();
- data = ConstructRandomSet(state.range(0));
- state.ResumeTiming();
- for (int j = 0; j < state.range(1); ++j)
- data.insert(RandomNumber());
- }
-}
-BENCHMARK(BM_SetInsert)
- ->Args({1<<10, 128})
- ->Args({2<<10, 128})
- ->Args({4<<10, 128})
- ->Args({8<<10, 128})
- ->Args({1<<10, 512})
- ->Args({2<<10, 512})
- ->Args({4<<10, 512})
- ->Args({8<<10, 512});
-```
-
-The preceding code is quite repetitive, and can be replaced with the following
-short-hand. The following macro will pick a few appropriate arguments in the
-product of the two specified ranges and will generate a benchmark for each such
-pair.
-
-```c++
-BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}});
-```
-
-For more complex patterns of inputs, passing a custom function to `Apply` allows
-programmatic specification of an arbitrary set of arguments on which to run the
-benchmark. The following example enumerates a dense range on one parameter,
-and a sparse range on the second.
-
-```c++
-static void CustomArguments(benchmark::internal::Benchmark* b) {
- for (int i = 0; i <= 10; ++i)
- for (int j = 32; j <= 1024*1024; j *= 8)
- b->Args({i, j});
-}
-BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
-```
-
-#### Passing Arbitrary Arguments to a Benchmark
-
-In C++11 it is possible to define a benchmark that takes an arbitrary number
-of extra arguments. The `BENCHMARK_CAPTURE(func, test_case_name, ...args)`
-macro creates a benchmark that invokes `func` with the `benchmark::State` as
-the first argument followed by the specified `args...`.
-The `test_case_name` is appended to the name of the benchmark and
-should describe the values passed.
-
-```c++
-template <class ...ExtraArgs>
-void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
- [...]
-}
-// Registers a benchmark named "BM_takes_args/int_string_test" that passes
-// the specified values to `extra_args`.
-BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
-```
-
-Note that elements of `...args` may refer to global variables. Users should
-avoid modifying global state inside of a benchmark.
-
-<a name="asymptotic-complexity" />
-
-### Calculating Asymptotic Complexity (Big O)
-
-Asymptotic complexity might be calculated for a family of benchmarks. The
-following code will calculate the coefficient for the high-order term in the
-running time and the normalized root-mean square error of string comparison.
-
-```c++
-static void BM_StringCompare(benchmark::State& state) {
- std::string s1(state.range(0), '-');
- std::string s2(state.range(0), '-');
- for (auto _ : state) {
- benchmark::DoNotOptimize(s1.compare(s2));
- }
- state.SetComplexityN(state.range(0));
-}
-BENCHMARK(BM_StringCompare)
- ->RangeMultiplier(2)->Range(1<<10, 1<<18)->Complexity(benchmark::oN);
-```
-
-As shown in the following invocation, asymptotic complexity might also be
-calculated automatically.
-
-```c++
-BENCHMARK(BM_StringCompare)
- ->RangeMultiplier(2)->Range(1<<10, 1<<18)->Complexity();
-```
-
-The following code will specify asymptotic complexity with a lambda function,
-that might be used to customize high-order term calculation.
-
-```c++
-BENCHMARK(BM_StringCompare)->RangeMultiplier(2)
- ->Range(1<<10, 1<<18)->Complexity([](benchmark::IterationCount n)->double{return n; });
-```
-
-<a name="templated-benchmarks" />
-
-### Templated Benchmarks
-
-This example produces and consumes messages of size `sizeof(v)` `range_x`
-times. It also outputs throughput in the absence of multiprogramming.
-
-```c++
-template <class Q> void BM_Sequential(benchmark::State& state) {
- Q q;
- typename Q::value_type v;
- for (auto _ : state) {
- for (int i = state.range(0); i--; )
- q.push(v);
- for (int e = state.range(0); e--; )
- q.Wait(&v);
- }
- // actually messages, not bytes:
- state.SetBytesProcessed(
- static_cast<int64_t>(state.iterations())*state.range(0));
-}
-BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
-```
-
-Three macros are provided for adding benchmark templates.
-
-```c++
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE(func, ...) // Takes any number of parameters.
-#else // C++ < C++11
-#define BENCHMARK_TEMPLATE(func, arg1)
-#endif
-#define BENCHMARK_TEMPLATE1(func, arg1)
-#define BENCHMARK_TEMPLATE2(func, arg1, arg2)
-```
-
-<a name="fixtures" />
-
-### Fixtures
-
-Fixture tests are created by first defining a type that derives from
-`::benchmark::Fixture` and then creating/registering the tests using the
-following macros:
-
-* `BENCHMARK_F(ClassName, Method)`
-* `BENCHMARK_DEFINE_F(ClassName, Method)`
-* `BENCHMARK_REGISTER_F(ClassName, Method)`
-
-For Example:
-
-```c++
-class MyFixture : public benchmark::Fixture {
-public:
- void SetUp(const ::benchmark::State& state) {
- }
-
- void TearDown(const ::benchmark::State& state) {
- }
-};
-
-BENCHMARK_F(MyFixture, FooTest)(benchmark::State& st) {
- for (auto _ : st) {
- ...
- }
-}
-
-BENCHMARK_DEFINE_F(MyFixture, BarTest)(benchmark::State& st) {
- for (auto _ : st) {
- ...
- }
-}
-/* BarTest is NOT registered */
-BENCHMARK_REGISTER_F(MyFixture, BarTest)->Threads(2);
-/* BarTest is now registered */
-```
-
-#### Templated Fixtures
-
-Also you can create templated fixture by using the following macros:
-
-* `BENCHMARK_TEMPLATE_F(ClassName, Method, ...)`
-* `BENCHMARK_TEMPLATE_DEFINE_F(ClassName, Method, ...)`
-
-For example:
-
-```c++
-template<typename T>
-class MyFixture : public benchmark::Fixture {};
-
-BENCHMARK_TEMPLATE_F(MyFixture, IntTest, int)(benchmark::State& st) {
- for (auto _ : st) {
- ...
- }
-}
-
-BENCHMARK_TEMPLATE_DEFINE_F(MyFixture, DoubleTest, double)(benchmark::State& st) {
- for (auto _ : st) {
- ...
- }
-}
-
-BENCHMARK_REGISTER_F(MyFixture, DoubleTest)->Threads(2);
-```
-
-<a name="custom-counters" />
-
-### Custom Counters
-
-You can add your own counters with user-defined names. The example below
-will add columns "Foo", "Bar" and "Baz" in its output:
-
-```c++
-static void UserCountersExample1(benchmark::State& state) {
- double numFoos = 0, numBars = 0, numBazs = 0;
- for (auto _ : state) {
- // ... count Foo,Bar,Baz events
- }
- state.counters["Foo"] = numFoos;
- state.counters["Bar"] = numBars;
- state.counters["Baz"] = numBazs;
-}
-```
-
-The `state.counters` object is a `std::map` with `std::string` keys
-and `Counter` values. The latter is a `double`-like class, via an implicit
-conversion to `double&`. Thus you can use all of the standard arithmetic
-assignment operators (`=,+=,-=,*=,/=`) to change the value of each counter.
-
-In multithreaded benchmarks, each counter is set on the calling thread only.
-When the benchmark finishes, the counters from each thread will be summed;
-the resulting sum is the value which will be shown for the benchmark.
-
-The `Counter` constructor accepts three parameters: the value as a `double`
-; a bit flag which allows you to show counters as rates, and/or as per-thread
-iteration, and/or as per-thread averages, and/or iteration invariants,
-and/or finally inverting the result; and a flag specifying the 'unit' - i.e.
-is 1k a 1000 (default, `benchmark::Counter::OneK::kIs1000`), or 1024
-(`benchmark::Counter::OneK::kIs1024`)?
-
-```c++
- // sets a simple counter
- state.counters["Foo"] = numFoos;
-
- // Set the counter as a rate. It will be presented divided
- // by the duration of the benchmark.
- // Meaning: per one second, how many 'foo's are processed?
- state.counters["FooRate"] = Counter(numFoos, benchmark::Counter::kIsRate);
-
- // Set the counter as a rate. It will be presented divided
- // by the duration of the benchmark, and the result inverted.
- // Meaning: how many seconds it takes to process one 'foo'?
- state.counters["FooInvRate"] = Counter(numFoos, benchmark::Counter::kIsRate | benchmark::Counter::kInvert);
-
- // Set the counter as a thread-average quantity. It will
- // be presented divided by the number of threads.
- state.counters["FooAvg"] = Counter(numFoos, benchmark::Counter::kAvgThreads);
-
- // There's also a combined flag:
- state.counters["FooAvgRate"] = Counter(numFoos,benchmark::Counter::kAvgThreadsRate);
-
- // This says that we process with the rate of state.range(0) bytes every iteration:
- state.counters["BytesProcessed"] = Counter(state.range(0), benchmark::Counter::kIsIterationInvariantRate, benchmark::Counter::OneK::kIs1024);
-```
-
-When you're compiling in C++11 mode or later you can use `insert()` with
-`std::initializer_list`:
-
-```c++
- // With C++11, this can be done:
- state.counters.insert({{"Foo", numFoos}, {"Bar", numBars}, {"Baz", numBazs}});
- // ... instead of:
- state.counters["Foo"] = numFoos;
- state.counters["Bar"] = numBars;
- state.counters["Baz"] = numBazs;
-```
-
-#### Counter Reporting
-
-When using the console reporter, by default, user counters are printed at
-the end after the table, the same way as ``bytes_processed`` and
-``items_processed``. This is best for cases in which there are few counters,
-or where there are only a couple of lines per benchmark. Here's an example of
-the default output:
-
-```
-------------------------------------------------------------------------------
-Benchmark Time CPU Iterations UserCounters...
-------------------------------------------------------------------------------
-BM_UserCounter/threads:8 2248 ns 10277 ns 68808 Bar=16 Bat=40 Baz=24 Foo=8
-BM_UserCounter/threads:1 9797 ns 9788 ns 71523 Bar=2 Bat=5 Baz=3 Foo=1024m
-BM_UserCounter/threads:2 4924 ns 9842 ns 71036 Bar=4 Bat=10 Baz=6 Foo=2
-BM_UserCounter/threads:4 2589 ns 10284 ns 68012 Bar=8 Bat=20 Baz=12 Foo=4
-BM_UserCounter/threads:8 2212 ns 10287 ns 68040 Bar=16 Bat=40 Baz=24 Foo=8
-BM_UserCounter/threads:16 1782 ns 10278 ns 68144 Bar=32 Bat=80 Baz=48 Foo=16
-BM_UserCounter/threads:32 1291 ns 10296 ns 68256 Bar=64 Bat=160 Baz=96 Foo=32
-BM_UserCounter/threads:4 2615 ns 10307 ns 68040 Bar=8 Bat=20 Baz=12 Foo=4
-BM_Factorial 26 ns 26 ns 26608979 40320
-BM_Factorial/real_time 26 ns 26 ns 26587936 40320
-BM_CalculatePiRange/1 16 ns 16 ns 45704255 0
-BM_CalculatePiRange/8 73 ns 73 ns 9520927 3.28374
-BM_CalculatePiRange/64 609 ns 609 ns 1140647 3.15746
-BM_CalculatePiRange/512 4900 ns 4901 ns 142696 3.14355
-```
-
-If this doesn't suit you, you can print each counter as a table column by
-passing the flag `--benchmark_counters_tabular=true` to the benchmark
-application. This is best for cases in which there are a lot of counters, or
-a lot of lines per individual benchmark. Note that this will trigger a
-reprinting of the table header any time the counter set changes between
-individual benchmarks. Here's an example of corresponding output when
-`--benchmark_counters_tabular=true` is passed:
-
-```
----------------------------------------------------------------------------------------
-Benchmark Time CPU Iterations Bar Bat Baz Foo
----------------------------------------------------------------------------------------
-BM_UserCounter/threads:8 2198 ns 9953 ns 70688 16 40 24 8
-BM_UserCounter/threads:1 9504 ns 9504 ns 73787 2 5 3 1
-BM_UserCounter/threads:2 4775 ns 9550 ns 72606 4 10 6 2
-BM_UserCounter/threads:4 2508 ns 9951 ns 70332 8 20 12 4
-BM_UserCounter/threads:8 2055 ns 9933 ns 70344 16 40 24 8
-BM_UserCounter/threads:16 1610 ns 9946 ns 70720 32 80 48 16
-BM_UserCounter/threads:32 1192 ns 9948 ns 70496 64 160 96 32
-BM_UserCounter/threads:4 2506 ns 9949 ns 70332 8 20 12 4
---------------------------------------------------------------
-Benchmark Time CPU Iterations
---------------------------------------------------------------
-BM_Factorial 26 ns 26 ns 26392245 40320
-BM_Factorial/real_time 26 ns 26 ns 26494107 40320
-BM_CalculatePiRange/1 15 ns 15 ns 45571597 0
-BM_CalculatePiRange/8 74 ns 74 ns 9450212 3.28374
-BM_CalculatePiRange/64 595 ns 595 ns 1173901 3.15746
-BM_CalculatePiRange/512 4752 ns 4752 ns 147380 3.14355
-BM_CalculatePiRange/4k 37970 ns 37972 ns 18453 3.14184
-BM_CalculatePiRange/32k 303733 ns 303744 ns 2305 3.14162
-BM_CalculatePiRange/256k 2434095 ns 2434186 ns 288 3.1416
-BM_CalculatePiRange/1024k 9721140 ns 9721413 ns 71 3.14159
-BM_CalculatePi/threads:8 2255 ns 9943 ns 70936
-```
-
-Note above the additional header printed when the benchmark changes from
-``BM_UserCounter`` to ``BM_Factorial``. This is because ``BM_Factorial`` does
-not have the same counter set as ``BM_UserCounter``.
-
-<a name="multithreaded-benchmarks"/>
-
-### Multithreaded Benchmarks
-
-In a multithreaded test (benchmark invoked by multiple threads simultaneously),
-it is guaranteed that none of the threads will start until all have reached
-the start of the benchmark loop, and all will have finished before any thread
-exits the benchmark loop. (This behavior is also provided by the `KeepRunning()`
-API) As such, any global setup or teardown can be wrapped in a check against the thread
-index:
-
-```c++
-static void BM_MultiThreaded(benchmark::State& state) {
- if (state.thread_index == 0) {
- // Setup code here.
- }
- for (auto _ : state) {
- // Run the test as normal.
- }
- if (state.thread_index == 0) {
- // Teardown code here.
- }
-}
-BENCHMARK(BM_MultiThreaded)->Threads(2);
-```
-
-If the benchmarked code itself uses threads and you want to compare it to
-single-threaded code, you may want to use real-time ("wallclock") measurements
-for latency comparisons:
-
-```c++
-BENCHMARK(BM_test)->Range(8, 8<<10)->UseRealTime();
-```
-
-Without `UseRealTime`, CPU time is used by default.
-
-<a name="cpu-timers" />
-
-### CPU Timers
-
-By default, the CPU timer only measures the time spent by the main thread.
-If the benchmark itself uses threads internally, this measurement may not
-be what you are looking for. Instead, there is a way to measure the total
-CPU usage of the process, by all the threads.
-
-```c++
-void callee(int i);
-
-static void MyMain(int size) {
-#pragma omp parallel for
- for(int i = 0; i < size; i++)
- callee(i);
-}
-
-static void BM_OpenMP(benchmark::State& state) {
- for (auto _ : state)
- MyMain(state.range(0));
-}
-
-// Measure the time spent by the main thread, use it to decide for how long to
-// run the benchmark loop. Depending on the internal implementation detail may
-// measure to anywhere from near-zero (the overhead spent before/after work
-// handoff to worker thread[s]) to the whole single-thread time.
-BENCHMARK(BM_OpenMP)->Range(8, 8<<10);
-
-// Measure the user-visible time, the wall clock (literally, the time that
-// has passed on the clock on the wall), use it to decide for how long to
-// run the benchmark loop. This will always be meaningful, an will match the
-// time spent by the main thread in single-threaded case, in general decreasing
-// with the number of internal threads doing the work.
-BENCHMARK(BM_OpenMP)->Range(8, 8<<10)->UseRealTime();
-
-// Measure the total CPU consumption, use it to decide for how long to
-// run the benchmark loop. This will always measure to no less than the
-// time spent by the main thread in single-threaded case.
-BENCHMARK(BM_OpenMP)->Range(8, 8<<10)->MeasureProcessCPUTime();
-
-// A mixture of the last two. Measure the total CPU consumption, but use the
-// wall clock to decide for how long to run the benchmark loop.
-BENCHMARK(BM_OpenMP)->Range(8, 8<<10)->MeasureProcessCPUTime()->UseRealTime();
-```
-
-#### Controlling Timers
-
-Normally, the entire duration of the work loop (`for (auto _ : state) {}`)
-is measured. But sometimes, it is necessary to do some work inside of
-that loop, every iteration, but without counting that time to the benchmark time.
-That is possible, although it is not recommended, since it has high overhead.
-
-```c++
-static void BM_SetInsert_With_Timer_Control(benchmark::State& state) {
- std::set<int> data;
- for (auto _ : state) {
- state.PauseTiming(); // Stop timers. They will not count until they are resumed.
- data = ConstructRandomSet(state.range(0)); // Do something that should not be measured
- state.ResumeTiming(); // And resume timers. They are now counting again.
- // The rest will be measured.
- for (int j = 0; j < state.range(1); ++j)
- data.insert(RandomNumber());
- }
-}
-BENCHMARK(BM_SetInsert_With_Timer_Control)->Ranges({{1<<10, 8<<10}, {128, 512}});
-```
-
-<a name="manual-timing" />
-
-### Manual Timing
-
-For benchmarking something for which neither CPU time nor real-time are
-correct or accurate enough, completely manual timing is supported using
-the `UseManualTime` function.
-
-When `UseManualTime` is used, the benchmarked code must call
-`SetIterationTime` once per iteration of the benchmark loop to
-report the manually measured time.
-
-An example use case for this is benchmarking GPU execution (e.g. OpenCL
-or CUDA kernels, OpenGL or Vulkan or Direct3D draw calls), which cannot
-be accurately measured using CPU time or real-time. Instead, they can be
-measured accurately using a dedicated API, and these measurement results
-can be reported back with `SetIterationTime`.
-
-```c++
-static void BM_ManualTiming(benchmark::State& state) {
- int microseconds = state.range(0);
- std::chrono::duration<double, std::micro> sleep_duration {
- static_cast<double>(microseconds)
- };
-
- for (auto _ : state) {
- auto start = std::chrono::high_resolution_clock::now();
- // Simulate some useful workload with a sleep
- std::this_thread::sleep_for(sleep_duration);
- auto end = std::chrono::high_resolution_clock::now();
-
- auto elapsed_seconds =
- std::chrono::duration_cast<std::chrono::duration<double>>(
- end - start);
-
- state.SetIterationTime(elapsed_seconds.count());
- }
-}
-BENCHMARK(BM_ManualTiming)->Range(1, 1<<17)->UseManualTime();
-```
-
-<a name="setting-the-time-unit" />
-
-### Setting the Time Unit
-
-If a benchmark runs a few milliseconds it may be hard to visually compare the
-measured times, since the output data is given in nanoseconds per default. In
-order to manually set the time unit, you can specify it manually:
-
-```c++
-BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
-```
-
-<a name="preventing-optimization" />
-
-### Preventing Optimization
-
-To prevent a value or expression from being optimized away by the compiler
-the `benchmark::DoNotOptimize(...)` and `benchmark::ClobberMemory()`
-functions can be used.
-
-```c++
-static void BM_test(benchmark::State& state) {
- for (auto _ : state) {
- int x = 0;
- for (int i=0; i < 64; ++i) {
- benchmark::DoNotOptimize(x += i);
- }
- }
-}
-```
-
-`DoNotOptimize(<expr>)` forces the *result* of `<expr>` to be stored in either
-memory or a register. For GNU based compilers it acts as read/write barrier
-for global memory. More specifically it forces the compiler to flush pending
-writes to memory and reload any other values as necessary.
-
-Note that `DoNotOptimize(<expr>)` does not prevent optimizations on `<expr>`
-in any way. `<expr>` may even be removed entirely when the result is already
-known. For example:
-
-```c++
- /* Example 1: `<expr>` is removed entirely. */
- int foo(int x) { return x + 42; }
- while (...) DoNotOptimize(foo(0)); // Optimized to DoNotOptimize(42);
-
- /* Example 2: Result of '<expr>' is only reused */
- int bar(int) __attribute__((const));
- while (...) DoNotOptimize(bar(0)); // Optimized to:
- // int __result__ = bar(0);
- // while (...) DoNotOptimize(__result__);
-```
-
-The second tool for preventing optimizations is `ClobberMemory()`. In essence
-`ClobberMemory()` forces the compiler to perform all pending writes to global
-memory. Memory managed by block scope objects must be "escaped" using
-`DoNotOptimize(...)` before it can be clobbered. In the below example
-`ClobberMemory()` prevents the call to `v.push_back(42)` from being optimized
-away.
-
-```c++
-static void BM_vector_push_back(benchmark::State& state) {
- for (auto _ : state) {
- std::vector<int> v;
- v.reserve(1);
- benchmark::DoNotOptimize(v.data()); // Allow v.data() to be clobbered.
- v.push_back(42);
- benchmark::ClobberMemory(); // Force 42 to be written to memory.
- }
-}
-```
-
-Note that `ClobberMemory()` is only available for GNU or MSVC based compilers.
-
-<a name="reporting-statistics" />
-
-### Statistics: Reporting the Mean, Median and Standard Deviation of Repeated Benchmarks
-
-By default each benchmark is run once and that single result is reported.
-However benchmarks are often noisy and a single result may not be representative
-of the overall behavior. For this reason it's possible to repeatedly rerun the
-benchmark.
-
-The number of runs of each benchmark is specified globally by the
-`--benchmark_repetitions` flag or on a per benchmark basis by calling
-`Repetitions` on the registered benchmark object. When a benchmark is run more
-than once the mean, median and standard deviation of the runs will be reported.
-
-Additionally the `--benchmark_report_aggregates_only={true|false}`,
-`--benchmark_display_aggregates_only={true|false}` flags or
-`ReportAggregatesOnly(bool)`, `DisplayAggregatesOnly(bool)` functions can be
-used to change how repeated tests are reported. By default the result of each
-repeated run is reported. When `report aggregates only` option is `true`,
-only the aggregates (i.e. mean, median and standard deviation, maybe complexity
-measurements if they were requested) of the runs is reported, to both the
-reporters - standard output (console), and the file.
-However when only the `display aggregates only` option is `true`,
-only the aggregates are displayed in the standard output, while the file
-output still contains everything.
-Calling `ReportAggregatesOnly(bool)` / `DisplayAggregatesOnly(bool)` on a
-registered benchmark object overrides the value of the appropriate flag for that
-benchmark.
-
-<a name="custom-statistics" />
-
-### Custom Statistics
-
-While having mean, median and standard deviation is nice, this may not be
-enough for everyone. For example you may want to know what the largest
-observation is, e.g. because you have some real-time constraints. This is easy.
-The following code will specify a custom statistic to be calculated, defined
-by a lambda function.
-
-```c++
-void BM_spin_empty(benchmark::State& state) {
- for (auto _ : state) {
- for (int x = 0; x < state.range(0); ++x) {
- benchmark::DoNotOptimize(x);
- }
- }
-}
-
-BENCHMARK(BM_spin_empty)
- ->ComputeStatistics("max", [](const std::vector<double>& v) -> double {
- return *(std::max_element(std::begin(v), std::end(v)));
- })
- ->Arg(512);
-```
-
-<a name="using-register-benchmark" />
-
-### Using RegisterBenchmark(name, fn, args...)
-
-The `RegisterBenchmark(name, func, args...)` function provides an alternative
-way to create and register benchmarks.
-`RegisterBenchmark(name, func, args...)` creates, registers, and returns a
-pointer to a new benchmark with the specified `name` that invokes
-`func(st, args...)` where `st` is a `benchmark::State` object.
-
-Unlike the `BENCHMARK` registration macros, which can only be used at the global
-scope, the `RegisterBenchmark` can be called anywhere. This allows for
-benchmark tests to be registered programmatically.
-
-Additionally `RegisterBenchmark` allows any callable object to be registered
-as a benchmark. Including capturing lambdas and function objects.
-
-For Example:
-```c++
-auto BM_test = [](benchmark::State& st, auto Inputs) { /* ... */ };
-
-int main(int argc, char** argv) {
- for (auto& test_input : { /* ... */ })
- benchmark::RegisterBenchmark(test_input.name(), BM_test, test_input);
- benchmark::Initialize(&argc, argv);
- benchmark::RunSpecifiedBenchmarks();
-}
-```
-
-<a name="exiting-with-an-error" />
-
-### Exiting with an Error
-
-When errors caused by external influences, such as file I/O and network
-communication, occur within a benchmark the
-`State::SkipWithError(const char* msg)` function can be used to skip that run
-of benchmark and report the error. Note that only future iterations of the
-`KeepRunning()` are skipped. For the ranged-for version of the benchmark loop
-Users must explicitly exit the loop, otherwise all iterations will be performed.
-Users may explicitly return to exit the benchmark immediately.
-
-The `SkipWithError(...)` function may be used at any point within the benchmark,
-including before and after the benchmark loop. Moreover, if `SkipWithError(...)`
-has been used, it is not required to reach the benchmark loop and one may return
-from the benchmark function early.
-
-For example:
-
-```c++
-static void BM_test(benchmark::State& state) {
- auto resource = GetResource();
- if (!resource.good()) {
- state.SkipWithError("Resource is not good!");
- // KeepRunning() loop will not be entered.
- }
- while (state.KeepRunning()) {
- auto data = resource.read_data();
- if (!resource.good()) {
- state.SkipWithError("Failed to read data!");
- break; // Needed to skip the rest of the iteration.
- }
- do_stuff(data);
- }
-}
-
-static void BM_test_ranged_fo(benchmark::State & state) {
- auto resource = GetResource();
- if (!resource.good()) {
- state.SkipWithError("Resource is not good!");
- return; // Early return is allowed when SkipWithError() has been used.
- }
- for (auto _ : state) {
- auto data = resource.read_data();
- if (!resource.good()) {
- state.SkipWithError("Failed to read data!");
- break; // REQUIRED to prevent all further iterations.
- }
- do_stuff(data);
- }
-}
-```
-<a name="a-faster-keep-running-loop" />
-
-### A Faster KeepRunning Loop
-
-In C++11 mode, a ranged-based for loop should be used in preference to
-the `KeepRunning` loop for running the benchmarks. For example:
-
-```c++
-static void BM_Fast(benchmark::State &state) {
- for (auto _ : state) {
- FastOperation();
- }
-}
-BENCHMARK(BM_Fast);
-```
-
-The reason the ranged-for loop is faster than using `KeepRunning`, is
-because `KeepRunning` requires a memory load and store of the iteration count
-ever iteration, whereas the ranged-for variant is able to keep the iteration count
-in a register.
-
-For example, an empty inner loop of using the ranged-based for method looks like:
-
-```asm
-# Loop Init
- mov rbx, qword ptr [r14 + 104]
- call benchmark::State::StartKeepRunning()
- test rbx, rbx
- je .LoopEnd
-.LoopHeader: # =>This Inner Loop Header: Depth=1
- add rbx, -1
- jne .LoopHeader
-.LoopEnd:
-```
-
-Compared to an empty `KeepRunning` loop, which looks like:
-
-```asm
-.LoopHeader: # in Loop: Header=BB0_3 Depth=1
- cmp byte ptr [rbx], 1
- jne .LoopInit
-.LoopBody: # =>This Inner Loop Header: Depth=1
- mov rax, qword ptr [rbx + 8]
- lea rcx, [rax + 1]
- mov qword ptr [rbx + 8], rcx
- cmp rax, qword ptr [rbx + 104]
- jb .LoopHeader
- jmp .LoopEnd
-.LoopInit:
- mov rdi, rbx
- call benchmark::State::StartKeepRunning()
- jmp .LoopBody
-.LoopEnd:
-```
-
-Unless C++03 compatibility is required, the ranged-for variant of writing
-the benchmark loop should be preferred.
-
-<a name="disabling-cpu-frequency-scaling" />
-
-### Disabling CPU Frequency Scaling
-
-If you see this error:
-
-```
-***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead.
-```
-
-you might want to disable the CPU frequency scaling while running the benchmark:
-
-```bash
-sudo cpupower frequency-set --governor performance
-./mybench
-sudo cpupower frequency-set --governor powersave
-```
+++ /dev/null
-workspace(name = "com_github_google_benchmark")
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
-http_archive(
- name = "rules_cc",
- strip_prefix = "rules_cc-a508235df92e71d537fcbae0c7c952ea6957a912",
- urls = ["https://github.com/bazelbuild/rules_cc/archive/a508235df92e71d537fcbae0c7c952ea6957a912.zip"],
-)
-
-http_archive(
- name = "com_google_googletest",
- strip_prefix = "googletest-3f0cf6b62ad1eb50d8736538363d3580dd640c3e",
- urls = ["https://github.com/google/googletest/archive/3f0cf6b62ad1eb50d8736538363d3580dd640c3e.zip"],
-)
-
-http_archive(
- name = "pybind11",
- build_file = "@//bindings/python:pybind11.BUILD",
- sha256 = "1eed57bc6863190e35637290f97a20c81cfe4d9090ac0a24f3bbf08f265eb71d",
- strip_prefix = "pybind11-2.4.3",
- urls = ["https://github.com/pybind/pybind11/archive/v2.4.3.tar.gz"],
-)
-
-new_local_repository(
- name = "python_headers",
- build_file = "@//bindings/python:python_headers.BUILD",
- path = "/usr/include/python3.6", # May be overwritten by setup.py.
-)
-
+++ /dev/null
-theme: jekyll-theme-midnight
\ No newline at end of file
+++ /dev/null
-version: '{build}'
-
-image: Visual Studio 2017
-
-configuration:
- - Debug
- - Release
-
-environment:
- matrix:
- - compiler: msvc-15-seh
- generator: "Visual Studio 15 2017"
-
- - compiler: msvc-15-seh
- generator: "Visual Studio 15 2017 Win64"
-
- - compiler: msvc-14-seh
- generator: "Visual Studio 14 2015"
-
- - compiler: msvc-14-seh
- generator: "Visual Studio 14 2015 Win64"
-
- - compiler: gcc-5.3.0-posix
- generator: "MinGW Makefiles"
- cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin'
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
-
-matrix:
- fast_finish: true
-
-install:
- # git bash conflicts with MinGW makefiles
- - if "%generator%"=="MinGW Makefiles" (set "PATH=%PATH:C:\Program Files\Git\usr\bin;=%")
- - if not "%cxx_path%"=="" (set "PATH=%PATH%;%cxx_path%")
-
-build_script:
- - md _build -Force
- - cd _build
- - echo %configuration%
- - cmake -G "%generator%" "-DCMAKE_BUILD_TYPE=%configuration%" -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON ..
- - cmake --build . --config %configuration%
-
-test_script:
- - ctest --build-config %configuration% --timeout 300 --output-on-failure
-
-artifacts:
- - path: '_build/CMakeFiles/*.log'
- name: logs
- - path: '_build/Testing/**/*.xml'
- name: test_results
+++ /dev/null
-exports_files(glob(["*.BUILD"]))
-exports_files(["build_defs.bzl"])
-
+++ /dev/null
-load("//bindings/python:build_defs.bzl", "py_extension")
-
-py_library(
- name = "benchmark",
- srcs = ["__init__.py"],
- visibility = ["//visibility:public"],
- deps = [
- ":_benchmark",
- # pip; absl:app
- ],
-)
-
-py_extension(
- name = "_benchmark",
- srcs = ["benchmark.cc"],
- copts = [
- "-fexceptions",
- "-fno-strict-aliasing",
- ],
- features = ["-use_header_modules"],
- deps = [
- "//:benchmark",
- "@pybind11",
- "@python_headers",
- ],
-)
-
-py_test(
- name = "example",
- srcs = ["example.py"],
- python_version = "PY3",
- srcs_version = "PY3",
- visibility = ["//visibility:public"],
- deps = [
- ":benchmark",
- ],
-)
-
+++ /dev/null
-# Copyright 2020 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Python benchmarking utilities.
-
-Example usage:
- import benchmark
-
- @benchmark.register
- def my_benchmark(state):
- ... # Code executed outside `while` loop is not timed.
-
- while state:
- ... # Code executed within `while` loop is timed.
-
- if __name__ == '__main__':
- benchmark.main()
-"""
-
-from absl import app
-from benchmark import _benchmark
-
-__all__ = [
- "register",
- "main",
-]
-
-__version__ = "0.1.0"
-
-
-def register(f=None, *, name=None):
- if f is None:
- return lambda f: register(f, name=name)
- if name is None:
- name = f.__name__
- _benchmark.RegisterBenchmark(name, f)
- return f
-
-
-def _flags_parser(argv):
- argv = _benchmark.Initialize(argv)
- return app.parse_flags_with_usage(argv)
-
-
-def _run_benchmarks(argv):
- if len(argv) > 1:
- raise app.UsageError('Too many command-line arguments.')
- return _benchmark.RunSpecifiedBenchmarks()
-
-
-def main(argv=None):
- return app.run(_run_benchmarks, argv=argv, flags_parser=_flags_parser)
+++ /dev/null
-// Benchmark for Python.
-
-#include "benchmark/benchmark.h"
-#include "pybind11/pybind11.h"
-#include "pybind11/stl.h"
-
-namespace {
-namespace py = ::pybind11;
-
-std::vector<std::string> Initialize(const std::vector<std::string>& argv) {
- // The `argv` pointers here become invalid when this function returns, but
- // benchmark holds the pointer to `argv[0]`. We create a static copy of it
- // so it persists, and replace the pointer below.
- static std::string executable_name(argv[0]);
- std::vector<char*> ptrs;
- ptrs.reserve(argv.size());
- for (auto& arg : argv) {
- ptrs.push_back(const_cast<char*>(arg.c_str()));
- }
- ptrs[0] = const_cast<char*>(executable_name.c_str());
- int argc = static_cast<int>(argv.size());
- benchmark::Initialize(&argc, ptrs.data());
- std::vector<std::string> remaining_argv;
- remaining_argv.reserve(argc);
- for (int i = 0; i < argc; ++i) {
- remaining_argv.emplace_back(ptrs[i]);
- }
- return remaining_argv;
-}
-
-void RegisterBenchmark(const char* name, py::function f) {
- benchmark::RegisterBenchmark(name, [f](benchmark::State& state) {
- f(&state);
- });
-}
-
-PYBIND11_MODULE(_benchmark, m) {
- m.def("Initialize", Initialize);
- m.def("RegisterBenchmark", RegisterBenchmark);
- m.def("RunSpecifiedBenchmarks",
- []() { benchmark::RunSpecifiedBenchmarks(); });
-
- py::class_<benchmark::State>(m, "State")
- .def("__bool__", &benchmark::State::KeepRunning)
- .def_property_readonly("keep_running", &benchmark::State::KeepRunning);
-};
-} // namespace
+++ /dev/null
-# Copyright 2020 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Example of Python using C++ benchmark framework."""
-
-import benchmark
-
-
-@benchmark.register
-def empty(state):
- while state:
- pass
-
-
-@benchmark.register
-def sum_million(state):
- while state:
- sum(range(1_000_000))
-
-
-if __name__ == '__main__':
- benchmark.main()
+++ /dev/null
-_SHARED_LIB_SUFFIX = {
- "//conditions:default": ".so",
- "//:windows": ".dll",
-}
-
-def py_extension(name, srcs, hdrs = [], copts = [], features = [], deps = []):
- for shared_lib_suffix in _SHARED_LIB_SUFFIX.values():
- shared_lib_name = name + shared_lib_suffix
- native.cc_binary(
- name = shared_lib_name,
- linkshared = 1,
- linkstatic = 1,
- srcs = srcs + hdrs,
- copts = copts,
- features = features,
- deps = deps,
- )
-
- return native.py_library(
- name = name,
- data = select({
- platform: [name + shared_lib_suffix]
- for platform, shared_lib_suffix in _SHARED_LIB_SUFFIX.items()
- }),
- )
+++ /dev/null
-cc_library(
- name = "pybind11",
- hdrs = glob(
- include = [
- "include/pybind11/*.h",
- "include/pybind11/detail/*.h",
- ],
- exclude = [
- "include/pybind11/common.h",
- "include/pybind11/eigen.h",
- ],
- ),
- copts = [
- "-fexceptions",
- "-Wno-undefined-inline",
- "-Wno-pragma-once-outside-header",
- ],
- includes = ["include"],
- visibility = ["//visibility:public"],
-)
+++ /dev/null
-cc_library(
- name = "python_headers",
- hdrs = glob(["**/*.h"]),
- includes = ["."],
- visibility = ["//visibility:public"],
-)
+++ /dev/null
-absl-py>=0.7.1
-
+++ /dev/null
-# - Adds a compiler flag if it is supported by the compiler
-#
-# This function checks that the supplied compiler flag is supported and then
-# adds it to the corresponding compiler flags
-#
-# add_cxx_compiler_flag(<FLAG> [<VARIANT>])
-#
-# - Example
-#
-# include(AddCXXCompilerFlag)
-# add_cxx_compiler_flag(-Wall)
-# add_cxx_compiler_flag(-no-strict-aliasing RELEASE)
-# Requires CMake 2.6+
-
-if(__add_cxx_compiler_flag)
- return()
-endif()
-set(__add_cxx_compiler_flag INCLUDED)
-
-include(CheckCXXCompilerFlag)
-
-function(mangle_compiler_flag FLAG OUTPUT)
- string(TOUPPER "HAVE_CXX_FLAG_${FLAG}" SANITIZED_FLAG)
- string(REPLACE "+" "X" SANITIZED_FLAG ${SANITIZED_FLAG})
- string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SANITIZED_FLAG ${SANITIZED_FLAG})
- string(REGEX REPLACE "_+" "_" SANITIZED_FLAG ${SANITIZED_FLAG})
- set(${OUTPUT} "${SANITIZED_FLAG}" PARENT_SCOPE)
-endfunction(mangle_compiler_flag)
-
-function(add_cxx_compiler_flag FLAG)
- mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
- set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}")
- check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
- set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
- if(${MANGLED_FLAG})
- set(VARIANT ${ARGV1})
- if(ARGV1)
- string(TOUPPER "_${VARIANT}" VARIANT)
- endif()
- set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${BENCHMARK_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
- endif()
-endfunction()
-
-function(add_required_cxx_compiler_flag FLAG)
- mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
- set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}")
- check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
- set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
- if(${MANGLED_FLAG})
- set(VARIANT ${ARGV1})
- if(ARGV1)
- string(TOUPPER "_${VARIANT}" VARIANT)
- endif()
- set(CMAKE_CXX_FLAGS${VARIANT} "${CMAKE_CXX_FLAGS${VARIANT}} ${FLAG}" PARENT_SCOPE)
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
- set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
- set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAG}" PARENT_SCOPE)
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${FLAG}" PARENT_SCOPE)
- else()
- message(FATAL_ERROR "Required flag '${FLAG}' is not supported by the compiler")
- endif()
-endfunction()
-
-function(check_cxx_warning_flag FLAG)
- mangle_compiler_flag("${FLAG}" MANGLED_FLAG)
- set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
- # Add -Werror to ensure the compiler generates an error if the warning flag
- # doesn't exist.
- set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror ${FLAG}")
- check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG})
- set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
-endfunction()
+++ /dev/null
-# - Compile and run code to check for C++ features
-#
-# This functions compiles a source file under the `cmake` folder
-# and adds the corresponding `HAVE_[FILENAME]` flag to the CMake
-# environment
-#
-# cxx_feature_check(<FLAG> [<VARIANT>])
-#
-# - Example
-#
-# include(CXXFeatureCheck)
-# cxx_feature_check(STD_REGEX)
-# Requires CMake 2.8.12+
-
-if(__cxx_feature_check)
- return()
-endif()
-set(__cxx_feature_check INCLUDED)
-
-function(cxx_feature_check FILE)
- string(TOLOWER ${FILE} FILE)
- string(TOUPPER ${FILE} VAR)
- string(TOUPPER "HAVE_${VAR}" FEATURE)
- if (DEFINED HAVE_${VAR})
- set(HAVE_${VAR} 1 PARENT_SCOPE)
- add_definitions(-DHAVE_${VAR})
- return()
- endif()
-
- if (NOT DEFINED COMPILE_${FEATURE})
- message(STATUS "Performing Test ${FEATURE}")
- if(CMAKE_CROSSCOMPILING)
- try_compile(COMPILE_${FEATURE}
- ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
- CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS}
- LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES})
- if(COMPILE_${FEATURE})
- message(WARNING
- "If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0")
- set(RUN_${FEATURE} 0 CACHE INTERNAL "")
- else()
- set(RUN_${FEATURE} 1 CACHE INTERNAL "")
- endif()
- else()
- message(STATUS "Performing Test ${FEATURE}")
- try_run(RUN_${FEATURE} COMPILE_${FEATURE}
- ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp
- CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS}
- LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES})
- endif()
- endif()
-
- if(RUN_${FEATURE} EQUAL 0)
- message(STATUS "Performing Test ${FEATURE} -- success")
- set(HAVE_${VAR} 1 PARENT_SCOPE)
- add_definitions(-DHAVE_${VAR})
- else()
- if(NOT COMPILE_${FEATURE})
- message(STATUS "Performing Test ${FEATURE} -- failed to compile")
- else()
- message(STATUS "Performing Test ${FEATURE} -- compiled but failed to run")
- endif()
- endif()
-endfunction()
+++ /dev/null
-include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
+++ /dev/null
-# - Returns a version string from Git tags
-#
-# This function inspects the annotated git tags for the project and returns a string
-# into a CMake variable
-#
-# get_git_version(<var>)
-#
-# - Example
-#
-# include(GetGitVersion)
-# get_git_version(GIT_VERSION)
-#
-# Requires CMake 2.8.11+
-find_package(Git)
-
-if(__get_git_version)
- return()
-endif()
-set(__get_git_version INCLUDED)
-
-function(get_git_version var)
- if(GIT_EXECUTABLE)
- execute_process(COMMAND ${GIT_EXECUTABLE} describe --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- RESULT_VARIABLE status
- OUTPUT_VARIABLE GIT_VERSION
- ERROR_QUIET)
- if(${status})
- set(GIT_VERSION "v0.0.0")
- else()
- string(STRIP ${GIT_VERSION} GIT_VERSION)
- string(REGEX REPLACE "-[0-9]+-g" "-" GIT_VERSION ${GIT_VERSION})
- endif()
-
- # Work out if the repository is dirty
- execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- OUTPUT_QUIET
- ERROR_QUIET)
- execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
- OUTPUT_VARIABLE GIT_DIFF_INDEX
- ERROR_QUIET)
- string(COMPARE NOTEQUAL "${GIT_DIFF_INDEX}" "" GIT_DIRTY)
- if (${GIT_DIRTY})
- set(GIT_VERSION "${GIT_VERSION}-dirty")
- endif()
- else()
- set(GIT_VERSION "v0.0.0")
- endif()
-
- message(STATUS "git Version: ${GIT_VERSION}")
- set(${var} ${GIT_VERSION} PARENT_SCOPE)
-endfunction()
+++ /dev/null
-# Download and unpack googletest at configure time
-set(GOOGLETEST_PREFIX "${benchmark_BINARY_DIR}/third_party/googletest")
-configure_file(${benchmark_SOURCE_DIR}/cmake/GoogleTest.cmake.in ${GOOGLETEST_PREFIX}/CMakeLists.txt @ONLY)
-
-set(GOOGLETEST_PATH "${CMAKE_CURRENT_SOURCE_DIR}/googletest" CACHE PATH "") # Mind the quotes
-execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
- -DALLOW_DOWNLOADING_GOOGLETEST=${BENCHMARK_DOWNLOAD_DEPENDENCIES} -DGOOGLETEST_PATH:PATH=${GOOGLETEST_PATH} .
- RESULT_VARIABLE result
- WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
-)
-
-if(result)
- message(FATAL_ERROR "CMake step for googletest failed: ${result}")
-endif()
-
-execute_process(
- COMMAND ${CMAKE_COMMAND} --build .
- RESULT_VARIABLE result
- WORKING_DIRECTORY ${GOOGLETEST_PREFIX}
-)
-
-if(result)
- message(FATAL_ERROR "Build step for googletest failed: ${result}")
-endif()
-
-# Prevent overriding the parent project's compiler/linker
-# settings on Windows
-set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
-
-include(${GOOGLETEST_PREFIX}/googletest-paths.cmake)
-
-# Add googletest directly to our build. This defines
-# the gtest and gtest_main targets.
-add_subdirectory(${GOOGLETEST_SOURCE_DIR}
- ${GOOGLETEST_BINARY_DIR}
- EXCLUDE_FROM_ALL)
-
-set_target_properties(gtest PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gtest,INTERFACE_INCLUDE_DIRECTORIES>)
-set_target_properties(gtest_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gtest_main,INTERFACE_INCLUDE_DIRECTORIES>)
-set_target_properties(gmock PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gmock,INTERFACE_INCLUDE_DIRECTORIES>)
-set_target_properties(gmock_main PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES $<TARGET_PROPERTY:gmock_main,INTERFACE_INCLUDE_DIRECTORIES>)
+++ /dev/null
-cmake_minimum_required(VERSION 2.8.12)
-
-project(googletest-download NONE)
-
-# Enable ExternalProject CMake module
-include(ExternalProject)
-
-option(ALLOW_DOWNLOADING_GOOGLETEST "If googletest src tree is not found in location specified by GOOGLETEST_PATH, do fetch the archive from internet" OFF)
-set(GOOGLETEST_PATH "/usr/src/googletest" CACHE PATH
- "Path to the googletest root tree. Should contain googletest and googlemock subdirs. And CMakeLists.txt in root, and in both of these subdirs")
-
-# Download and install GoogleTest
-
-message(STATUS "Looking for Google Test sources")
-message(STATUS "Looking for Google Test sources in ${GOOGLETEST_PATH}")
-if(EXISTS "${GOOGLETEST_PATH}" AND IS_DIRECTORY "${GOOGLETEST_PATH}" AND EXISTS "${GOOGLETEST_PATH}/CMakeLists.txt" AND
- EXISTS "${GOOGLETEST_PATH}/googletest" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googletest" AND EXISTS "${GOOGLETEST_PATH}/googletest/CMakeLists.txt" AND
- EXISTS "${GOOGLETEST_PATH}/googlemock" AND IS_DIRECTORY "${GOOGLETEST_PATH}/googlemock" AND EXISTS "${GOOGLETEST_PATH}/googlemock/CMakeLists.txt")
- message(STATUS "Found Google Test in ${GOOGLETEST_PATH}")
-
- ExternalProject_Add(
- googletest
- PREFIX "${CMAKE_BINARY_DIR}"
- DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download"
- SOURCE_DIR "${GOOGLETEST_PATH}" # use existing src dir.
- BINARY_DIR "${CMAKE_BINARY_DIR}/build"
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- TEST_COMMAND ""
- )
-else()
- if(NOT ALLOW_DOWNLOADING_GOOGLETEST)
- message(SEND_ERROR "Did not find Google Test sources! Either pass correct path in GOOGLETEST_PATH, or enable ALLOW_DOWNLOADING_GOOGLETEST, or disable BENCHMARK_ENABLE_GTEST_TESTS / BENCHMARK_ENABLE_TESTING.")
- else()
- message(WARNING "Did not find Google Test sources! Fetching from web...")
- ExternalProject_Add(
- googletest
- GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG master
- PREFIX "${CMAKE_BINARY_DIR}"
- STAMP_DIR "${CMAKE_BINARY_DIR}/stamp"
- DOWNLOAD_DIR "${CMAKE_BINARY_DIR}/download"
- SOURCE_DIR "${CMAKE_BINARY_DIR}/src"
- BINARY_DIR "${CMAKE_BINARY_DIR}/build"
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- TEST_COMMAND ""
- )
- endif()
-endif()
-
-ExternalProject_Get_Property(googletest SOURCE_DIR BINARY_DIR)
-file(WRITE googletest-paths.cmake
-"set(GOOGLETEST_SOURCE_DIR \"${SOURCE_DIR}\")
-set(GOOGLETEST_BINARY_DIR \"${BINARY_DIR}\")
-")
+++ /dev/null
-prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=${prefix}
-libdir=${prefix}/lib
-includedir=${prefix}/include
-
-Name: @PROJECT_NAME@
-Description: Google microbenchmark framework
-Version: @VERSION@
-
-Libs: -L${libdir} -lbenchmark
-Libs.private: -lpthread
-Cflags: -I${includedir}
+++ /dev/null
-#include <gnuregex.h>
-#include <string>
-int main() {
- std::string str = "test0159";
- regex_t re;
- int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB);
- if (ec != 0) {
- return ec;
- }
- return regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0;
-}
-
+++ /dev/null
-find_package(LLVMAr REQUIRED)
-set(CMAKE_AR "${LLVMAR_EXECUTABLE}" CACHE FILEPATH "" FORCE)
-
-find_package(LLVMNm REQUIRED)
-set(CMAKE_NM "${LLVMNM_EXECUTABLE}" CACHE FILEPATH "" FORCE)
-
-find_package(LLVMRanLib REQUIRED)
-set(CMAKE_RANLIB "${LLVMRANLIB_EXECUTABLE}" CACHE FILEPATH "" FORCE)
+++ /dev/null
-#include <regex.h>
-#include <string>
-int main() {
- std::string str = "test0159";
- regex_t re;
- int ec = regcomp(&re, "^[a-z]+[0-9]+$", REG_EXTENDED | REG_NOSUB);
- if (ec != 0) {
- return ec;
- }
- int ret = regexec(&re, str.c_str(), 0, nullptr, 0) ? -1 : 0;
- regfree(&re);
- return ret;
-}
-
+++ /dev/null
-macro(split_list listname)
- string(REPLACE ";" " " ${listname} "${${listname}}")
-endmacro()
+++ /dev/null
-#include <regex>
-#include <string>
-int main() {
- const std::string str = "test0159";
- std::regex re;
- re = std::regex("^[a-z]+[0-9]+$",
- std::regex_constants::extended | std::regex_constants::nosubs);
- return std::regex_search(str, re) ? 0 : -1;
-}
-
+++ /dev/null
-#include <chrono>
-
-int main() {
- typedef std::chrono::steady_clock Clock;
- Clock::time_point tp = Clock::now();
- ((void)tp);
-}
+++ /dev/null
-#define HAVE_THREAD_SAFETY_ATTRIBUTES
-#include "../src/mutex.h"
-
-int main() {}
+++ /dev/null
-cmake_minimum_required(VERSION 2.8.11)
-project(cmake_wrapper)
-
-include(conanbuildinfo.cmake)
-conan_basic_setup()
-
-include(${CMAKE_SOURCE_DIR}/CMakeListsOriginal.txt)
+++ /dev/null
-cmake_minimum_required(VERSION 2.8.11)
-project(test_package)
-
-set(CMAKE_VERBOSE_MAKEFILE TRUE)
-
-include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
-conan_basic_setup()
-
-add_executable(${PROJECT_NAME} test_package.cpp)
-target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-from conans import ConanFile, CMake
-import os
-
-
-class TestPackageConan(ConanFile):
- settings = "os", "compiler", "build_type", "arch"
- generators = "cmake"
-
- def build(self):
- cmake = CMake(self)
- cmake.configure()
- cmake.build()
-
- def test(self):
- bin_path = os.path.join("bin", "test_package")
- self.run(bin_path, run_environment=True)
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-void BM_StringCreation(benchmark::State& state) {
- while (state.KeepRunning())
- std::string empty_string;
-}
-
-BENCHMARK(BM_StringCreation);
-
-void BM_StringCopy(benchmark::State& state) {
- std::string x = "hello";
- while (state.KeepRunning())
- std::string copy(x);
-}
-
-BENCHMARK(BM_StringCopy);
-
-BENCHMARK_MAIN();
+++ /dev/null
-from conans import ConanFile, CMake, tools
-from conans.errors import ConanInvalidConfiguration
-import shutil
-import os
-
-
-class GoogleBenchmarkConan(ConanFile):
- name = "benchmark"
- description = "A microbenchmark support library."
- topics = ("conan", "benchmark", "google", "microbenchmark")
- url = "https://github.com/google/benchmark"
- homepage = "https://github.com/google/benchmark"
- author = "Google Inc."
- license = "Apache-2.0"
- exports_sources = ["*"]
- generators = "cmake"
-
- settings = "arch", "build_type", "compiler", "os"
- options = {
- "shared": [True, False],
- "fPIC": [True, False],
- "enable_lto": [True, False],
- "enable_exceptions": [True, False]
- }
- default_options = {"shared": False, "fPIC": True, "enable_lto": False, "enable_exceptions": True}
-
- _build_subfolder = "."
-
- def source(self):
- # Wrap the original CMake file to call conan_basic_setup
- shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt")
- shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt")
-
- def config_options(self):
- if self.settings.os == "Windows":
- if self.settings.compiler == "Visual Studio" and float(self.settings.compiler.version.value) <= 12:
- raise ConanInvalidConfiguration("{} {} does not support Visual Studio <= 12".format(self.name, self.version))
- del self.options.fPIC
-
- def configure(self):
- if self.settings.os == "Windows" and self.options.shared:
- raise ConanInvalidConfiguration("Windows shared builds are not supported right now, see issue #639")
-
- def _configure_cmake(self):
- cmake = CMake(self)
-
- cmake.definitions["BENCHMARK_ENABLE_TESTING"] = "OFF"
- cmake.definitions["BENCHMARK_ENABLE_GTEST_TESTS"] = "OFF"
- cmake.definitions["BENCHMARK_ENABLE_LTO"] = "ON" if self.options.enable_lto else "OFF"
- cmake.definitions["BENCHMARK_ENABLE_EXCEPTIONS"] = "ON" if self.options.enable_exceptions else "OFF"
-
- # See https://github.com/google/benchmark/pull/638 for Windows 32 build explanation
- if self.settings.os != "Windows":
- cmake.definitions["BENCHMARK_BUILD_32_BITS"] = "ON" if "64" not in str(self.settings.arch) else "OFF"
- cmake.definitions["BENCHMARK_USE_LIBCXX"] = "ON" if (str(self.settings.compiler.libcxx) == "libc++") else "OFF"
- else:
- cmake.definitions["BENCHMARK_USE_LIBCXX"] = "OFF"
-
- cmake.configure(build_folder=self._build_subfolder)
- return cmake
-
- def build(self):
- cmake = self._configure_cmake()
- cmake.build()
-
- def package(self):
- cmake = self._configure_cmake()
- cmake.install()
-
- self.copy(pattern="LICENSE", dst="licenses")
-
- def package_info(self):
- self.cpp_info.libs = tools.collect_libs(self)
- if self.settings.os == "Linux":
- self.cpp_info.libs.extend(["pthread", "rt"])
- elif self.settings.os == "Windows":
- self.cpp_info.libs.append("shlwapi")
- elif self.settings.os == "SunOS":
- self.cpp_info.libs.append("kstat")
+++ /dev/null
-# Build tool dependency policy
-
-To ensure the broadest compatibility when building the benchmark library, but
-still allow forward progress, we require any build tooling to be available for:
-
-* Debian stable AND
-* The last two Ubuntu LTS releases AND
-
-Currently, this means using build tool versions that are available for Ubuntu
-16.04 (Xenial), Ubuntu 18.04 (Bionic), and Debian stretch.
-
-_Note, [travis](.travis.yml) runs under Ubuntu 14.04 (Trusty) for linux builds._
-
-## cmake
-The current supported version is cmake 3.5.1 as of 2018-06-06.
-
-_Note, this version is also available for Ubuntu 14.04, the previous Ubuntu LTS
-release, as `cmake3`._
+++ /dev/null
-# Assembly Tests
-
-The Benchmark library provides a number of functions whose primary
-purpose in to affect assembly generation, including `DoNotOptimize`
-and `ClobberMemory`. In addition there are other functions,
-such as `KeepRunning`, for which generating good assembly is paramount.
-
-For these functions it's important to have tests that verify the
-correctness and quality of the implementation. This requires testing
-the code generated by the compiler.
-
-This document describes how the Benchmark library tests compiler output,
-as well as how to properly write new tests.
-
-
-## Anatomy of a Test
-
-Writing a test has two steps:
-
-* Write the code you want to generate assembly for.
-* Add `// CHECK` lines to match against the verified assembly.
-
-Example:
-```c++
-
-// CHECK-LABEL: test_add:
-extern "C" int test_add() {
- extern int ExternInt;
- return ExternInt + 1;
-
- // CHECK: movl ExternInt(%rip), %eax
- // CHECK: addl %eax
- // CHECK: ret
-}
-
-```
-
-#### LLVM Filecheck
-
-[LLVM's Filecheck](https://llvm.org/docs/CommandGuide/FileCheck.html)
-is used to test the generated assembly against the `// CHECK` lines
-specified in the tests source file. Please see the documentation
-linked above for information on how to write `CHECK` directives.
-
-#### Tips and Tricks:
-
-* Tests should match the minimal amount of output required to establish
-correctness. `CHECK` directives don't have to match on the exact next line
-after the previous match, so tests should omit checks for unimportant
-bits of assembly. ([`CHECK-NEXT`](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-next-directive)
-can be used to ensure a match occurs exactly after the previous match).
-
-* The tests are compiled with `-O3 -g0`. So we're only testing the
-optimized output.
-
-* The assembly output is further cleaned up using `tools/strip_asm.py`.
-This removes comments, assembler directives, and unused labels before
-the test is run.
-
-* The generated and stripped assembly file for a test is output under
-`<build-directory>/test/<test-name>.s`
-
-* Filecheck supports using [`CHECK` prefixes](https://llvm.org/docs/CommandGuide/FileCheck.html#cmdoption-check-prefixes)
-to specify lines that should only match in certain situations.
-The Benchmark tests use `CHECK-CLANG` and `CHECK-GNU` for lines that
-are only expected to match Clang or GCC's output respectively. Normal
-`CHECK` lines match against all compilers. (Note: `CHECK-NOT` and
-`CHECK-LABEL` are NOT prefixes. They are versions of non-prefixed
-`CHECK` lines)
-
-* Use `extern "C"` to disable name mangling for specific functions. This
-makes them easier to name in the `CHECK` lines.
-
-
-## Problems Writing Portable Tests
-
-Writing tests which check the code generated by a compiler are
-inherently non-portable. Different compilers and even different compiler
-versions may generate entirely different code. The Benchmark tests
-must tolerate this.
-
-LLVM Filecheck provides a number of mechanisms to help write
-"more portable" tests; including [matching using regular expressions](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-pattern-matching-syntax),
-allowing the creation of [named variables](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-variables)
-for later matching, and [checking non-sequential matches](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-dag-directive).
-
-#### Capturing Variables
-
-For example, say GCC stores a variable in a register but Clang stores
-it in memory. To write a test that tolerates both cases we "capture"
-the destination of the store, and then use the captured expression
-to write the remainder of the test.
-
-```c++
-// CHECK-LABEL: test_div_no_op_into_shr:
-extern "C" void test_div_no_op_into_shr(int value) {
- int divisor = 2;
- benchmark::DoNotOptimize(divisor); // hide the value from the optimizer
- return value / divisor;
-
- // CHECK: movl $2, [[DEST:.*]]
- // CHECK: idivl [[DEST]]
- // CHECK: ret
-}
-```
-
-#### Using Regular Expressions to Match Differing Output
-
-Often tests require testing assembly lines which may subtly differ
-between compilers or compiler versions. A common example of this
-is matching stack frame addresses. In this case regular expressions
-can be used to match the differing bits of output. For example:
-
-```c++
-int ExternInt;
-struct Point { int x, y, z; };
-
-// CHECK-LABEL: test_store_point:
-extern "C" void test_store_point() {
- Point p{ExternInt, ExternInt, ExternInt};
- benchmark::DoNotOptimize(p);
-
- // CHECK: movl ExternInt(%rip), %eax
- // CHECK: movl %eax, -{{[0-9]+}}(%rsp)
- // CHECK: movl %eax, -{{[0-9]+}}(%rsp)
- // CHECK: movl %eax, -{{[0-9]+}}(%rsp)
- // CHECK: ret
-}
-```
-
-## Current Requirements and Limitations
-
-The tests require Filecheck to be installed along the `PATH` of the
-build machine. Otherwise the tests will be disabled.
-
-Additionally, as mentioned in the previous section, codegen tests are
-inherently non-portable. Currently the tests are limited to:
-
-* x86_64 targets.
-* Compiled with GCC or Clang
-
-Further work could be done, at least on a limited basis, to extend the
-tests to other architectures and compilers (using `CHECK` prefixes).
-
-Furthermore, the tests fail for builds which specify additional flags
-that modify code generation, including `--coverage` or `-fsanitize=`.
-
+++ /dev/null
-theme: jekyll-theme-midnight
\ No newline at end of file
+++ /dev/null
-# Benchmark Tools
-
-## compare.py
-
-The `compare.py` can be used to compare the result of benchmarks.
-
-**NOTE**: the utility relies on the scipy package which can be installed using [these instructions](https://www.scipy.org/install.html).
-
-### Displaying aggregates only
-
-The switch `-a` / `--display_aggregates_only` can be used to control the
-displayment of the normal iterations vs the aggregates. When passed, it will
-be passthrough to the benchmark binaries to be run, and will be accounted for
-in the tool itself; only the aggregates will be displayed, but not normal runs.
-It only affects the display, the separate runs will still be used to calculate
-the U test.
-
-### Modes of operation
-
-There are three modes of operation:
-
-1. Just compare two benchmarks
-The program is invoked like:
-
-``` bash
-$ compare.py benchmarks <benchmark_baseline> <benchmark_contender> [benchmark options]...
-```
-Where `<benchmark_baseline>` and `<benchmark_contender>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file.
-
-`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes.
-
-Example output:
-```
-$ ./compare.py benchmarks ./a.out ./a.out
-RUNNING: ./a.out --benchmark_out=/tmp/tmprBT5nW
-Run on (8 X 4000 MHz CPU s)
-2017-11-07 21:16:44
-------------------------------------------------------
-Benchmark Time CPU Iterations
-------------------------------------------------------
-BM_memcpy/8 36 ns 36 ns 19101577 211.669MB/s
-BM_memcpy/64 76 ns 76 ns 9412571 800.199MB/s
-BM_memcpy/512 84 ns 84 ns 8249070 5.64771GB/s
-BM_memcpy/1024 116 ns 116 ns 6181763 8.19505GB/s
-BM_memcpy/8192 643 ns 643 ns 1062855 11.8636GB/s
-BM_copy/8 222 ns 222 ns 3137987 34.3772MB/s
-BM_copy/64 1608 ns 1608 ns 432758 37.9501MB/s
-BM_copy/512 12589 ns 12589 ns 54806 38.7867MB/s
-BM_copy/1024 25169 ns 25169 ns 27713 38.8003MB/s
-BM_copy/8192 201165 ns 201112 ns 3486 38.8466MB/s
-RUNNING: ./a.out --benchmark_out=/tmp/tmpt1wwG_
-Run on (8 X 4000 MHz CPU s)
-2017-11-07 21:16:53
-------------------------------------------------------
-Benchmark Time CPU Iterations
-------------------------------------------------------
-BM_memcpy/8 36 ns 36 ns 19397903 211.255MB/s
-BM_memcpy/64 73 ns 73 ns 9691174 839.635MB/s
-BM_memcpy/512 85 ns 85 ns 8312329 5.60101GB/s
-BM_memcpy/1024 118 ns 118 ns 6438774 8.11608GB/s
-BM_memcpy/8192 656 ns 656 ns 1068644 11.6277GB/s
-BM_copy/8 223 ns 223 ns 3146977 34.2338MB/s
-BM_copy/64 1611 ns 1611 ns 435340 37.8751MB/s
-BM_copy/512 12622 ns 12622 ns 54818 38.6844MB/s
-BM_copy/1024 25257 ns 25239 ns 27779 38.6927MB/s
-BM_copy/8192 205013 ns 205010 ns 3479 38.108MB/s
-Comparing ./a.out to ./a.out
-Benchmark Time CPU Time Old Time New CPU Old CPU New
-------------------------------------------------------------------------------------------------------
-BM_memcpy/8 +0.0020 +0.0020 36 36 36 36
-BM_memcpy/64 -0.0468 -0.0470 76 73 76 73
-BM_memcpy/512 +0.0081 +0.0083 84 85 84 85
-BM_memcpy/1024 +0.0098 +0.0097 116 118 116 118
-BM_memcpy/8192 +0.0200 +0.0203 643 656 643 656
-BM_copy/8 +0.0046 +0.0042 222 223 222 223
-BM_copy/64 +0.0020 +0.0020 1608 1611 1608 1611
-BM_copy/512 +0.0027 +0.0026 12589 12622 12589 12622
-BM_copy/1024 +0.0035 +0.0028 25169 25257 25169 25239
-BM_copy/8192 +0.0191 +0.0194 201165 205013 201112 205010
-```
-
-What it does is for the every benchmark from the first run it looks for the benchmark with exactly the same name in the second run, and then compares the results. If the names differ, the benchmark is omitted from the diff.
-As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`.
-
-2. Compare two different filters of one benchmark
-The program is invoked like:
-
-``` bash
-$ compare.py filters <benchmark> <filter_baseline> <filter_contender> [benchmark options]...
-```
-Where `<benchmark>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file.
-
-Where `<filter_baseline>` and `<filter_contender>` are the same regex filters that you would pass to the `[--benchmark_filter=<regex>]` parameter of the benchmark binary.
-
-`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes.
-
-Example output:
-```
-$ ./compare.py filters ./a.out BM_memcpy BM_copy
-RUNNING: ./a.out --benchmark_filter=BM_memcpy --benchmark_out=/tmp/tmpBWKk0k
-Run on (8 X 4000 MHz CPU s)
-2017-11-07 21:37:28
-------------------------------------------------------
-Benchmark Time CPU Iterations
-------------------------------------------------------
-BM_memcpy/8 36 ns 36 ns 17891491 211.215MB/s
-BM_memcpy/64 74 ns 74 ns 9400999 825.646MB/s
-BM_memcpy/512 87 ns 87 ns 8027453 5.46126GB/s
-BM_memcpy/1024 111 ns 111 ns 6116853 8.5648GB/s
-BM_memcpy/8192 657 ns 656 ns 1064679 11.6247GB/s
-RUNNING: ./a.out --benchmark_filter=BM_copy --benchmark_out=/tmp/tmpAvWcOM
-Run on (8 X 4000 MHz CPU s)
-2017-11-07 21:37:33
-----------------------------------------------------
-Benchmark Time CPU Iterations
-----------------------------------------------------
-BM_copy/8 227 ns 227 ns 3038700 33.6264MB/s
-BM_copy/64 1640 ns 1640 ns 426893 37.2154MB/s
-BM_copy/512 12804 ns 12801 ns 55417 38.1444MB/s
-BM_copy/1024 25409 ns 25407 ns 27516 38.4365MB/s
-BM_copy/8192 202986 ns 202990 ns 3454 38.4871MB/s
-Comparing BM_memcpy to BM_copy (from ./a.out)
-Benchmark Time CPU Time Old Time New CPU Old CPU New
---------------------------------------------------------------------------------------------------------------------
-[BM_memcpy vs. BM_copy]/8 +5.2829 +5.2812 36 227 36 227
-[BM_memcpy vs. BM_copy]/64 +21.1719 +21.1856 74 1640 74 1640
-[BM_memcpy vs. BM_copy]/512 +145.6487 +145.6097 87 12804 87 12801
-[BM_memcpy vs. BM_copy]/1024 +227.1860 +227.1776 111 25409 111 25407
-[BM_memcpy vs. BM_copy]/8192 +308.1664 +308.2898 657 202986 656 202990
-```
-
-As you can see, it applies filter to the benchmarks, both when running the benchmark, and before doing the diff. And to make the diff work, the matches are replaced with some common string. Thus, you can compare two different benchmark families within one benchmark binary.
-As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`.
-
-3. Compare filter one from benchmark one to filter two from benchmark two:
-The program is invoked like:
-
-``` bash
-$ compare.py filters <benchmark_baseline> <filter_baseline> <benchmark_contender> <filter_contender> [benchmark options]...
-```
-
-Where `<benchmark_baseline>` and `<benchmark_contender>` either specify a benchmark executable file, or a JSON output file. The type of the input file is automatically detected. If a benchmark executable is specified then the benchmark is run to obtain the results. Otherwise the results are simply loaded from the output file.
-
-Where `<filter_baseline>` and `<filter_contender>` are the same regex filters that you would pass to the `[--benchmark_filter=<regex>]` parameter of the benchmark binary.
-
-`[benchmark options]` will be passed to the benchmarks invocations. They can be anything that binary accepts, be it either normal `--benchmark_*` parameters, or some custom parameters your binary takes.
-
-Example output:
-```
-$ ./compare.py benchmarksfiltered ./a.out BM_memcpy ./a.out BM_copy
-RUNNING: ./a.out --benchmark_filter=BM_memcpy --benchmark_out=/tmp/tmp_FvbYg
-Run on (8 X 4000 MHz CPU s)
-2017-11-07 21:38:27
-------------------------------------------------------
-Benchmark Time CPU Iterations
-------------------------------------------------------
-BM_memcpy/8 37 ns 37 ns 18953482 204.118MB/s
-BM_memcpy/64 74 ns 74 ns 9206578 828.245MB/s
-BM_memcpy/512 91 ns 91 ns 8086195 5.25476GB/s
-BM_memcpy/1024 120 ns 120 ns 5804513 7.95662GB/s
-BM_memcpy/8192 664 ns 664 ns 1028363 11.4948GB/s
-RUNNING: ./a.out --benchmark_filter=BM_copy --benchmark_out=/tmp/tmpDfL5iE
-Run on (8 X 4000 MHz CPU s)
-2017-11-07 21:38:32
-----------------------------------------------------
-Benchmark Time CPU Iterations
-----------------------------------------------------
-BM_copy/8 230 ns 230 ns 2985909 33.1161MB/s
-BM_copy/64 1654 ns 1653 ns 419408 36.9137MB/s
-BM_copy/512 13122 ns 13120 ns 53403 37.2156MB/s
-BM_copy/1024 26679 ns 26666 ns 26575 36.6218MB/s
-BM_copy/8192 215068 ns 215053 ns 3221 36.3283MB/s
-Comparing BM_memcpy (from ./a.out) to BM_copy (from ./a.out)
-Benchmark Time CPU Time Old Time New CPU Old CPU New
---------------------------------------------------------------------------------------------------------------------
-[BM_memcpy vs. BM_copy]/8 +5.1649 +5.1637 37 230 37 230
-[BM_memcpy vs. BM_copy]/64 +21.4352 +21.4374 74 1654 74 1653
-[BM_memcpy vs. BM_copy]/512 +143.6022 +143.5865 91 13122 91 13120
-[BM_memcpy vs. BM_copy]/1024 +221.5903 +221.4790 120 26679 120 26666
-[BM_memcpy vs. BM_copy]/8192 +322.9059 +323.0096 664 215068 664 215053
-```
-This is a mix of the previous two modes, two (potentially different) benchmark binaries are run, and a different filter is applied to each one.
-As you can note, the values in `Time` and `CPU` columns are calculated as `(new - old) / |old|`.
-
-### U test
-
-If there is a sufficient repetition count of the benchmarks, the tool can do
-a [U Test](https://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test), of the
-null hypothesis that it is equally likely that a randomly selected value from
-one sample will be less than or greater than a randomly selected value from a
-second sample.
-
-If the calculated p-value is below this value is lower than the significance
-level alpha, then the result is said to be statistically significant and the
-null hypothesis is rejected. Which in other words means that the two benchmarks
-aren't identical.
-
-**WARNING**: requires **LARGE** (no less than 9) number of repetitions to be
-meaningful!
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Support for registering benchmarks for functions.
-
-/* Example usage:
-// Define a function that executes the code to be measured a
-// specified number of times:
-static void BM_StringCreation(benchmark::State& state) {
- for (auto _ : state)
- std::string empty_string;
-}
-
-// Register the function as a benchmark
-BENCHMARK(BM_StringCreation);
-
-// Define another benchmark
-static void BM_StringCopy(benchmark::State& state) {
- std::string x = "hello";
- for (auto _ : state)
- std::string copy(x);
-}
-BENCHMARK(BM_StringCopy);
-
-// Augment the main() program to invoke benchmarks if specified
-// via the --benchmarks command line flag. E.g.,
-// my_unittest --benchmark_filter=all
-// my_unittest --benchmark_filter=BM_StringCreation
-// my_unittest --benchmark_filter=String
-// my_unittest --benchmark_filter='Copy|Creation'
-int main(int argc, char** argv) {
- benchmark::Initialize(&argc, argv);
- benchmark::RunSpecifiedBenchmarks();
- return 0;
-}
-
-// Sometimes a family of microbenchmarks can be implemented with
-// just one routine that takes an extra argument to specify which
-// one of the family of benchmarks to run. For example, the following
-// code defines a family of microbenchmarks for measuring the speed
-// of memcpy() calls of different lengths:
-
-static void BM_memcpy(benchmark::State& state) {
- char* src = new char[state.range(0)]; char* dst = new char[state.range(0)];
- memset(src, 'x', state.range(0));
- for (auto _ : state)
- memcpy(dst, src, state.range(0));
- state.SetBytesProcessed(state.iterations() * state.range(0));
- delete[] src; delete[] dst;
-}
-BENCHMARK(BM_memcpy)->Arg(8)->Arg(64)->Arg(512)->Arg(1<<10)->Arg(8<<10);
-
-// The preceding code is quite repetitive, and can be replaced with the
-// following short-hand. The following invocation will pick a few
-// appropriate arguments in the specified range and will generate a
-// microbenchmark for each such argument.
-BENCHMARK(BM_memcpy)->Range(8, 8<<10);
-
-// You might have a microbenchmark that depends on two inputs. For
-// example, the following code defines a family of microbenchmarks for
-// measuring the speed of set insertion.
-static void BM_SetInsert(benchmark::State& state) {
- set<int> data;
- for (auto _ : state) {
- state.PauseTiming();
- data = ConstructRandomSet(state.range(0));
- state.ResumeTiming();
- for (int j = 0; j < state.range(1); ++j)
- data.insert(RandomNumber());
- }
-}
-BENCHMARK(BM_SetInsert)
- ->Args({1<<10, 128})
- ->Args({2<<10, 128})
- ->Args({4<<10, 128})
- ->Args({8<<10, 128})
- ->Args({1<<10, 512})
- ->Args({2<<10, 512})
- ->Args({4<<10, 512})
- ->Args({8<<10, 512});
-
-// The preceding code is quite repetitive, and can be replaced with
-// the following short-hand. The following macro will pick a few
-// appropriate arguments in the product of the two specified ranges
-// and will generate a microbenchmark for each such pair.
-BENCHMARK(BM_SetInsert)->Ranges({{1<<10, 8<<10}, {128, 512}});
-
-// For more complex patterns of inputs, passing a custom function
-// to Apply allows programmatic specification of an
-// arbitrary set of arguments to run the microbenchmark on.
-// The following example enumerates a dense range on
-// one parameter, and a sparse range on the second.
-static void CustomArguments(benchmark::internal::Benchmark* b) {
- for (int i = 0; i <= 10; ++i)
- for (int j = 32; j <= 1024*1024; j *= 8)
- b->Args({i, j});
-}
-BENCHMARK(BM_SetInsert)->Apply(CustomArguments);
-
-// Templated microbenchmarks work the same way:
-// Produce then consume 'size' messages 'iters' times
-// Measures throughput in the absence of multiprogramming.
-template <class Q> int BM_Sequential(benchmark::State& state) {
- Q q;
- typename Q::value_type v;
- for (auto _ : state) {
- for (int i = state.range(0); i--; )
- q.push(v);
- for (int e = state.range(0); e--; )
- q.Wait(&v);
- }
- // actually messages, not bytes:
- state.SetBytesProcessed(state.iterations() * state.range(0));
-}
-BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);
-
-Use `Benchmark::MinTime(double t)` to set the minimum time used to run the
-benchmark. This option overrides the `benchmark_min_time` flag.
-
-void BM_test(benchmark::State& state) {
- ... body ...
-}
-BENCHMARK(BM_test)->MinTime(2.0); // Run for at least 2 seconds.
-
-In a multithreaded test, it is guaranteed that none of the threads will start
-until all have reached the loop start, and all will have finished before any
-thread exits the loop body. As such, any global setup or teardown you want to
-do can be wrapped in a check against the thread index:
-
-static void BM_MultiThreaded(benchmark::State& state) {
- if (state.thread_index == 0) {
- // Setup code here.
- }
- for (auto _ : state) {
- // Run the test as normal.
- }
- if (state.thread_index == 0) {
- // Teardown code here.
- }
-}
-BENCHMARK(BM_MultiThreaded)->Threads(4);
-
-
-If a benchmark runs a few milliseconds it may be hard to visually compare the
-measured times, since the output data is given in nanoseconds per default. In
-order to manually set the time unit, you can specify it manually:
-
-BENCHMARK(BM_test)->Unit(benchmark::kMillisecond);
-*/
-
-#ifndef BENCHMARK_BENCHMARK_H_
-#define BENCHMARK_BENCHMARK_H_
-
-// The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer.
-#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
-#define BENCHMARK_HAS_CXX11
-#endif
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <iosfwd>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#if defined(BENCHMARK_HAS_CXX11)
-#include <initializer_list>
-#include <type_traits>
-#include <utility>
-#endif
-
-#if defined(_MSC_VER)
-#include <intrin.h> // for _ReadWriteBarrier
-#endif
-
-#ifndef BENCHMARK_HAS_CXX11
-#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- TypeName& operator=(const TypeName&)
-#else
-#define BENCHMARK_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&) = delete; \
- TypeName& operator=(const TypeName&) = delete
-#endif
-
-#if defined(__GNUC__)
-#define BENCHMARK_UNUSED __attribute__((unused))
-#define BENCHMARK_ALWAYS_INLINE __attribute__((always_inline))
-#define BENCHMARK_NOEXCEPT noexcept
-#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
-#elif defined(_MSC_VER) && !defined(__clang__)
-#define BENCHMARK_UNUSED
-#define BENCHMARK_ALWAYS_INLINE __forceinline
-#if _MSC_VER >= 1900
-#define BENCHMARK_NOEXCEPT noexcept
-#define BENCHMARK_NOEXCEPT_OP(x) noexcept(x)
-#else
-#define BENCHMARK_NOEXCEPT
-#define BENCHMARK_NOEXCEPT_OP(x)
-#endif
-#define __func__ __FUNCTION__
-#else
-#define BENCHMARK_UNUSED
-#define BENCHMARK_ALWAYS_INLINE
-#define BENCHMARK_NOEXCEPT
-#define BENCHMARK_NOEXCEPT_OP(x)
-#endif
-
-#define BENCHMARK_INTERNAL_TOSTRING2(x) #x
-#define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x)
-
-#if defined(__GNUC__) || defined(__clang__)
-#define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y)
-#define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg)))
-#else
-#define BENCHMARK_BUILTIN_EXPECT(x, y) x
-#define BENCHMARK_DEPRECATED_MSG(msg)
-#define BENCHMARK_WARNING_MSG(msg) \
- __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \
- __LINE__) ") : warning note: " msg))
-#endif
-
-#if defined(__GNUC__) && !defined(__clang__)
-#define BENCHMARK_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-#endif
-
-#ifndef __has_builtin
-#define __has_builtin(x) 0
-#endif
-
-#if defined(__GNUC__) || __has_builtin(__builtin_unreachable)
-#define BENCHMARK_UNREACHABLE() __builtin_unreachable()
-#elif defined(_MSC_VER)
-#define BENCHMARK_UNREACHABLE() __assume(false)
-#else
-#define BENCHMARK_UNREACHABLE() ((void)0)
-#endif
-
-namespace benchmark {
-class BenchmarkReporter;
-class MemoryManager;
-
-void Initialize(int* argc, char** argv);
-
-// Report to stdout all arguments in 'argv' as unrecognized except the first.
-// Returns true there is at least on unrecognized argument (i.e. 'argc' > 1).
-bool ReportUnrecognizedArguments(int argc, char** argv);
-
-// Generate a list of benchmarks matching the specified --benchmark_filter flag
-// and if --benchmark_list_tests is specified return after printing the name
-// of each matching benchmark. Otherwise run each matching benchmark and
-// report the results.
-//
-// The second and third overload use the specified 'display_reporter' and
-// 'file_reporter' respectively. 'file_reporter' will write to the file
-// specified
-// by '--benchmark_output'. If '--benchmark_output' is not given the
-// 'file_reporter' is ignored.
-//
-// RETURNS: The number of matching benchmarks.
-size_t RunSpecifiedBenchmarks();
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter);
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
- BenchmarkReporter* file_reporter);
-
-// Register a MemoryManager instance that will be used to collect and report
-// allocation measurements for benchmark runs.
-void RegisterMemoryManager(MemoryManager* memory_manager);
-
-namespace internal {
-class Benchmark;
-class BenchmarkImp;
-class BenchmarkFamilies;
-
-void UseCharPointer(char const volatile*);
-
-// Take ownership of the pointer and register the benchmark. Return the
-// registered benchmark.
-Benchmark* RegisterBenchmarkInternal(Benchmark*);
-
-// Ensure that the standard streams are properly initialized in every TU.
-int InitializeStreams();
-BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams();
-
-} // namespace internal
-
-#if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \
- defined(__EMSCRIPTEN__)
-#define BENCHMARK_HAS_NO_INLINE_ASSEMBLY
-#endif
-
-// The DoNotOptimize(...) function can be used to prevent a value or
-// expression from being optimized away by the compiler. This function is
-// intended to add little to no overhead.
-// See: https://youtu.be/nXaxk27zwlk?t=2441
-#ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
- asm volatile("" : : "r,m"(value) : "memory");
-}
-
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) {
-#if defined(__clang__)
- asm volatile("" : "+r,m"(value) : : "memory");
-#else
- asm volatile("" : "+m,r"(value) : : "memory");
-#endif
-}
-
-// Force the compiler to flush pending writes to global memory. Acts as an
-// effective read/write barrier
-inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() {
- asm volatile("" : : : "memory");
-}
-#elif defined(_MSC_VER)
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
- internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
- _ReadWriteBarrier();
-}
-
-inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { _ReadWriteBarrier(); }
-#else
-template <class Tp>
-inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) {
- internal::UseCharPointer(&reinterpret_cast<char const volatile&>(value));
-}
-// FIXME Add ClobberMemory() for non-gnu and non-msvc compilers
-#endif
-
-// This class is used for user-defined counters.
-class Counter {
- public:
- enum Flags {
- kDefaults = 0,
- // Mark the counter as a rate. It will be presented divided
- // by the duration of the benchmark.
- kIsRate = 1U << 0U,
- // Mark the counter as a thread-average quantity. It will be
- // presented divided by the number of threads.
- kAvgThreads = 1U << 1U,
- // Mark the counter as a thread-average rate. See above.
- kAvgThreadsRate = kIsRate | kAvgThreads,
- // Mark the counter as a constant value, valid/same for *every* iteration.
- // When reporting, it will be *multiplied* by the iteration count.
- kIsIterationInvariant = 1U << 2U,
- // Mark the counter as a constant rate.
- // When reporting, it will be *multiplied* by the iteration count
- // and then divided by the duration of the benchmark.
- kIsIterationInvariantRate = kIsRate | kIsIterationInvariant,
- // Mark the counter as a iteration-average quantity.
- // It will be presented divided by the number of iterations.
- kAvgIterations = 1U << 3U,
- // Mark the counter as a iteration-average rate. See above.
- kAvgIterationsRate = kIsRate | kAvgIterations,
-
- // In the end, invert the result. This is always done last!
- kInvert = 1U << 31U
- };
-
- enum OneK {
- // 1'000 items per 1k
- kIs1000 = 1000,
- // 1'024 items per 1k
- kIs1024 = 1024
- };
-
- double value;
- Flags flags;
- OneK oneK;
-
- BENCHMARK_ALWAYS_INLINE
- Counter(double v = 0., Flags f = kDefaults, OneK k = kIs1000)
- : value(v), flags(f), oneK(k) {}
-
- BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; }
- BENCHMARK_ALWAYS_INLINE operator double&() { return value; }
-};
-
-// A helper for user code to create unforeseen combinations of Flags, without
-// having to do this cast manually each time, or providing this operator.
-Counter::Flags inline operator|(const Counter::Flags& LHS,
- const Counter::Flags& RHS) {
- return static_cast<Counter::Flags>(static_cast<int>(LHS) |
- static_cast<int>(RHS));
-}
-
-// This is the container for the user-defined counters.
-typedef std::map<std::string, Counter> UserCounters;
-
-// TimeUnit is passed to a benchmark in order to specify the order of magnitude
-// for the measured time.
-enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond };
-
-// BigO is passed to a benchmark in order to specify the asymptotic
-// computational
-// complexity for the benchmark. In case oAuto is selected, complexity will be
-// calculated automatically to the best fit.
-enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda };
-
-typedef uint64_t IterationCount;
-
-// BigOFunc is passed to a benchmark in order to specify the asymptotic
-// computational complexity for the benchmark.
-typedef double(BigOFunc)(IterationCount);
-
-// StatisticsFunc is passed to a benchmark in order to compute some descriptive
-// statistics over all the measurements of some type
-typedef double(StatisticsFunc)(const std::vector<double>&);
-
-namespace internal {
-struct Statistics {
- std::string name_;
- StatisticsFunc* compute_;
-
- Statistics(const std::string& name, StatisticsFunc* compute)
- : name_(name), compute_(compute) {}
-};
-
-struct BenchmarkInstance;
-class ThreadTimer;
-class ThreadManager;
-
-enum AggregationReportMode
-#if defined(BENCHMARK_HAS_CXX11)
- : unsigned
-#else
-#endif
-{
- // The mode has not been manually specified
- ARM_Unspecified = 0,
- // The mode is user-specified.
- // This may or may not be set when the following bit-flags are set.
- ARM_Default = 1U << 0U,
- // File reporter should only output aggregates.
- ARM_FileReportAggregatesOnly = 1U << 1U,
- // Display reporter should only output aggregates
- ARM_DisplayReportAggregatesOnly = 1U << 2U,
- // Both reporters should only display aggregates.
- ARM_ReportAggregatesOnly =
- ARM_FileReportAggregatesOnly | ARM_DisplayReportAggregatesOnly
-};
-
-} // namespace internal
-
-// State is passed to a running Benchmark and contains state for the
-// benchmark to use.
-class State {
- public:
- struct StateIterator;
- friend struct StateIterator;
-
- // Returns iterators used to run each iteration of a benchmark using a
- // C++11 ranged-based for loop. These functions should not be called directly.
- //
- // REQUIRES: The benchmark has not started running yet. Neither begin nor end
- // have been called previously.
- //
- // NOTE: KeepRunning may not be used after calling either of these functions.
- BENCHMARK_ALWAYS_INLINE StateIterator begin();
- BENCHMARK_ALWAYS_INLINE StateIterator end();
-
- // Returns true if the benchmark should continue through another iteration.
- // NOTE: A benchmark may not return from the test until KeepRunning() has
- // returned false.
- bool KeepRunning();
-
- // Returns true iff the benchmark should run n more iterations.
- // REQUIRES: 'n' > 0.
- // NOTE: A benchmark must not return from the test until KeepRunningBatch()
- // has returned false.
- // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations.
- //
- // Intended usage:
- // while (state.KeepRunningBatch(1000)) {
- // // process 1000 elements
- // }
- bool KeepRunningBatch(IterationCount n);
-
- // REQUIRES: timer is running and 'SkipWithError(...)' has not been called
- // by the current thread.
- // Stop the benchmark timer. If not called, the timer will be
- // automatically stopped after the last iteration of the benchmark loop.
- //
- // For threaded benchmarks the PauseTiming() function only pauses the timing
- // for the current thread.
- //
- // NOTE: The "real time" measurement is per-thread. If different threads
- // report different measurements the largest one is reported.
- //
- // NOTE: PauseTiming()/ResumeTiming() are relatively
- // heavyweight, and so their use should generally be avoided
- // within each benchmark iteration, if possible.
- void PauseTiming();
-
- // REQUIRES: timer is not running and 'SkipWithError(...)' has not been called
- // by the current thread.
- // Start the benchmark timer. The timer is NOT running on entrance to the
- // benchmark function. It begins running after control flow enters the
- // benchmark loop.
- //
- // NOTE: PauseTiming()/ResumeTiming() are relatively
- // heavyweight, and so their use should generally be avoided
- // within each benchmark iteration, if possible.
- void ResumeTiming();
-
- // REQUIRES: 'SkipWithError(...)' has not been called previously by the
- // current thread.
- // Report the benchmark as resulting in an error with the specified 'msg'.
- // After this call the user may explicitly 'return' from the benchmark.
- //
- // If the ranged-for style of benchmark loop is used, the user must explicitly
- // break from the loop, otherwise all future iterations will be run.
- // If the 'KeepRunning()' loop is used the current thread will automatically
- // exit the loop at the end of the current iteration.
- //
- // For threaded benchmarks only the current thread stops executing and future
- // calls to `KeepRunning()` will block until all threads have completed
- // the `KeepRunning()` loop. If multiple threads report an error only the
- // first error message is used.
- //
- // NOTE: Calling 'SkipWithError(...)' does not cause the benchmark to exit
- // the current scope immediately. If the function is called from within
- // the 'KeepRunning()' loop the current iteration will finish. It is the users
- // responsibility to exit the scope as needed.
- void SkipWithError(const char* msg);
-
- // Returns true if an error has been reported with 'SkipWithError(...)'.
- bool error_occurred() const { return error_occurred_; }
-
- // REQUIRES: called exactly once per iteration of the benchmarking loop.
- // Set the manually measured time for this benchmark iteration, which
- // is used instead of automatically measured time if UseManualTime() was
- // specified.
- //
- // For threaded benchmarks the final value will be set to the largest
- // reported values.
- void SetIterationTime(double seconds);
-
- // Set the number of bytes processed by the current benchmark
- // execution. This routine is typically called once at the end of a
- // throughput oriented benchmark.
- //
- // REQUIRES: a benchmark has exited its benchmarking loop.
- BENCHMARK_ALWAYS_INLINE
- void SetBytesProcessed(int64_t bytes) {
- counters["bytes_per_second"] =
- Counter(static_cast<double>(bytes), Counter::kIsRate, Counter::kIs1024);
- }
-
- BENCHMARK_ALWAYS_INLINE
- int64_t bytes_processed() const {
- if (counters.find("bytes_per_second") != counters.end())
- return static_cast<int64_t>(counters.at("bytes_per_second"));
- return 0;
- }
-
- // If this routine is called with complexity_n > 0 and complexity report is
- // requested for the
- // family benchmark, then current benchmark will be part of the computation
- // and complexity_n will
- // represent the length of N.
- BENCHMARK_ALWAYS_INLINE
- void SetComplexityN(int64_t complexity_n) { complexity_n_ = complexity_n; }
-
- BENCHMARK_ALWAYS_INLINE
- int64_t complexity_length_n() const { return complexity_n_; }
-
- // If this routine is called with items > 0, then an items/s
- // label is printed on the benchmark report line for the currently
- // executing benchmark. It is typically called at the end of a processing
- // benchmark where a processing items/second output is desired.
- //
- // REQUIRES: a benchmark has exited its benchmarking loop.
- BENCHMARK_ALWAYS_INLINE
- void SetItemsProcessed(int64_t items) {
- counters["items_per_second"] =
- Counter(static_cast<double>(items), benchmark::Counter::kIsRate);
- }
-
- BENCHMARK_ALWAYS_INLINE
- int64_t items_processed() const {
- if (counters.find("items_per_second") != counters.end())
- return static_cast<int64_t>(counters.at("items_per_second"));
- return 0;
- }
-
- // If this routine is called, the specified label is printed at the
- // end of the benchmark report line for the currently executing
- // benchmark. Example:
- // static void BM_Compress(benchmark::State& state) {
- // ...
- // double compress = input_size / output_size;
- // state.SetLabel(StrFormat("compress:%.1f%%", 100.0*compression));
- // }
- // Produces output that looks like:
- // BM_Compress 50 50 14115038 compress:27.3%
- //
- // REQUIRES: a benchmark has exited its benchmarking loop.
- void SetLabel(const char* label);
-
- void BENCHMARK_ALWAYS_INLINE SetLabel(const std::string& str) {
- this->SetLabel(str.c_str());
- }
-
- // Range arguments for this run. CHECKs if the argument has been set.
- BENCHMARK_ALWAYS_INLINE
- int64_t range(std::size_t pos = 0) const {
- assert(range_.size() > pos);
- return range_[pos];
- }
-
- BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
- int64_t range_x() const { return range(0); }
-
- BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
- int64_t range_y() const { return range(1); }
-
- BENCHMARK_ALWAYS_INLINE
- IterationCount iterations() const {
- if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) {
- return 0;
- }
- return max_iterations - total_iterations_ + batch_leftover_;
- }
-
- private
- : // items we expect on the first cache line (ie 64 bytes of the struct)
- // When total_iterations_ is 0, KeepRunning() and friends will return false.
- // May be larger than max_iterations.
- IterationCount total_iterations_;
-
- // When using KeepRunningBatch(), batch_leftover_ holds the number of
- // iterations beyond max_iters that were run. Used to track
- // completed_iterations_ accurately.
- IterationCount batch_leftover_;
-
- public:
- const IterationCount max_iterations;
-
- private:
- bool started_;
- bool finished_;
- bool error_occurred_;
-
- private: // items we don't need on the first cache line
- std::vector<int64_t> range_;
-
- int64_t complexity_n_;
-
- public:
- // Container for user-defined counters.
- UserCounters counters;
- // Index of the executing thread. Values from [0, threads).
- const int thread_index;
- // Number of threads concurrently executing the benchmark.
- const int threads;
-
- private:
- State(IterationCount max_iters, const std::vector<int64_t>& ranges,
- int thread_i, int n_threads, internal::ThreadTimer* timer,
- internal::ThreadManager* manager);
-
- void StartKeepRunning();
- // Implementation of KeepRunning() and KeepRunningBatch().
- // is_batch must be true unless n is 1.
- bool KeepRunningInternal(IterationCount n, bool is_batch);
- void FinishKeepRunning();
- internal::ThreadTimer* timer_;
- internal::ThreadManager* manager_;
-
- friend struct internal::BenchmarkInstance;
-};
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() {
- return KeepRunningInternal(1, /*is_batch=*/false);
-}
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(IterationCount n) {
- return KeepRunningInternal(n, /*is_batch=*/true);
-}
-
-inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(IterationCount n,
- bool is_batch) {
- // total_iterations_ is set to 0 by the constructor, and always set to a
- // nonzero value by StartKepRunning().
- assert(n > 0);
- // n must be 1 unless is_batch is true.
- assert(is_batch || n == 1);
- if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) {
- total_iterations_ -= n;
- return true;
- }
- if (!started_) {
- StartKeepRunning();
- if (!error_occurred_ && total_iterations_ >= n) {
- total_iterations_ -= n;
- return true;
- }
- }
- // For non-batch runs, total_iterations_ must be 0 by now.
- if (is_batch && total_iterations_ != 0) {
- batch_leftover_ = n - total_iterations_;
- total_iterations_ = 0;
- return true;
- }
- FinishKeepRunning();
- return false;
-}
-
-struct State::StateIterator {
- struct BENCHMARK_UNUSED Value {};
- typedef std::forward_iterator_tag iterator_category;
- typedef Value value_type;
- typedef Value reference;
- typedef Value pointer;
- typedef std::ptrdiff_t difference_type;
-
- private:
- friend class State;
- BENCHMARK_ALWAYS_INLINE
- StateIterator() : cached_(0), parent_() {}
-
- BENCHMARK_ALWAYS_INLINE
- explicit StateIterator(State* st)
- : cached_(st->error_occurred_ ? 0 : st->max_iterations), parent_(st) {}
-
- public:
- BENCHMARK_ALWAYS_INLINE
- Value operator*() const { return Value(); }
-
- BENCHMARK_ALWAYS_INLINE
- StateIterator& operator++() {
- assert(cached_ > 0);
- --cached_;
- return *this;
- }
-
- BENCHMARK_ALWAYS_INLINE
- bool operator!=(StateIterator const&) const {
- if (BENCHMARK_BUILTIN_EXPECT(cached_ != 0, true)) return true;
- parent_->FinishKeepRunning();
- return false;
- }
-
- private:
- IterationCount cached_;
- State* const parent_;
-};
-
-inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::begin() {
- return StateIterator(this);
-}
-inline BENCHMARK_ALWAYS_INLINE State::StateIterator State::end() {
- StartKeepRunning();
- return StateIterator();
-}
-
-namespace internal {
-
-typedef void(Function)(State&);
-
-// ------------------------------------------------------
-// Benchmark registration object. The BENCHMARK() macro expands
-// into an internal::Benchmark* object. Various methods can
-// be called on this object to change the properties of the benchmark.
-// Each method returns "this" so that multiple method calls can
-// chained into one expression.
-class Benchmark {
- public:
- virtual ~Benchmark();
-
- // Note: the following methods all return "this" so that multiple
- // method calls can be chained together in one expression.
-
- // Run this benchmark once with "x" as the extra argument passed
- // to the function.
- // REQUIRES: The function passed to the constructor must accept an arg1.
- Benchmark* Arg(int64_t x);
-
- // Run this benchmark with the given time unit for the generated output report
- Benchmark* Unit(TimeUnit unit);
-
- // Run this benchmark once for a number of values picked from the
- // range [start..limit]. (start and limit are always picked.)
- // REQUIRES: The function passed to the constructor must accept an arg1.
- Benchmark* Range(int64_t start, int64_t limit);
-
- // Run this benchmark once for all values in the range [start..limit] with
- // specific step
- // REQUIRES: The function passed to the constructor must accept an arg1.
- Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1);
-
- // Run this benchmark once with "args" as the extra arguments passed
- // to the function.
- // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
- Benchmark* Args(const std::vector<int64_t>& args);
-
- // Equivalent to Args({x, y})
- // NOTE: This is a legacy C++03 interface provided for compatibility only.
- // New code should use 'Args'.
- Benchmark* ArgPair(int64_t x, int64_t y) {
- std::vector<int64_t> args;
- args.push_back(x);
- args.push_back(y);
- return Args(args);
- }
-
- // Run this benchmark once for a number of values picked from the
- // ranges [start..limit]. (starts and limits are always picked.)
- // REQUIRES: The function passed to the constructor must accept arg1, arg2 ...
- Benchmark* Ranges(const std::vector<std::pair<int64_t, int64_t> >& ranges);
-
- // Equivalent to ArgNames({name})
- Benchmark* ArgName(const std::string& name);
-
- // Set the argument names to display in the benchmark name. If not called,
- // only argument values will be shown.
- Benchmark* ArgNames(const std::vector<std::string>& names);
-
- // Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}).
- // NOTE: This is a legacy C++03 interface provided for compatibility only.
- // New code should use 'Ranges'.
- Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) {
- std::vector<std::pair<int64_t, int64_t> > ranges;
- ranges.push_back(std::make_pair(lo1, hi1));
- ranges.push_back(std::make_pair(lo2, hi2));
- return Ranges(ranges);
- }
-
- // Pass this benchmark object to *func, which can customize
- // the benchmark by calling various methods like Arg, Args,
- // Threads, etc.
- Benchmark* Apply(void (*func)(Benchmark* benchmark));
-
- // Set the range multiplier for non-dense range. If not called, the range
- // multiplier kRangeMultiplier will be used.
- Benchmark* RangeMultiplier(int multiplier);
-
- // Set the minimum amount of time to use when running this benchmark. This
- // option overrides the `benchmark_min_time` flag.
- // REQUIRES: `t > 0` and `Iterations` has not been called on this benchmark.
- Benchmark* MinTime(double t);
-
- // Specify the amount of iterations that should be run by this benchmark.
- // REQUIRES: 'n > 0' and `MinTime` has not been called on this benchmark.
- //
- // NOTE: This function should only be used when *exact* iteration control is
- // needed and never to control or limit how long a benchmark runs, where
- // `--benchmark_min_time=N` or `MinTime(...)` should be used instead.
- Benchmark* Iterations(IterationCount n);
-
- // Specify the amount of times to repeat this benchmark. This option overrides
- // the `benchmark_repetitions` flag.
- // REQUIRES: `n > 0`
- Benchmark* Repetitions(int n);
-
- // Specify if each repetition of the benchmark should be reported separately
- // or if only the final statistics should be reported. If the benchmark
- // is not repeated then the single result is always reported.
- // Applies to *ALL* reporters (display and file).
- Benchmark* ReportAggregatesOnly(bool value = true);
-
- // Same as ReportAggregatesOnly(), but applies to display reporter only.
- Benchmark* DisplayAggregatesOnly(bool value = true);
-
- // By default, the CPU time is measured only for the main thread, which may
- // be unrepresentative if the benchmark uses threads internally. If called,
- // the total CPU time spent by all the threads will be measured instead.
- // By default, the only the main thread CPU time will be measured.
- Benchmark* MeasureProcessCPUTime();
-
- // If a particular benchmark should use the Wall clock instead of the CPU time
- // (be it either the CPU time of the main thread only (default), or the
- // total CPU usage of the benchmark), call this method. If called, the elapsed
- // (wall) time will be used to control how many iterations are run, and in the
- // printing of items/second or MB/seconds values.
- // If not called, the CPU time used by the benchmark will be used.
- Benchmark* UseRealTime();
-
- // If a benchmark must measure time manually (e.g. if GPU execution time is
- // being
- // measured), call this method. If called, each benchmark iteration should
- // call
- // SetIterationTime(seconds) to report the measured time, which will be used
- // to control how many iterations are run, and in the printing of items/second
- // or MB/second values.
- Benchmark* UseManualTime();
-
- // Set the asymptotic computational complexity for the benchmark. If called
- // the asymptotic computational complexity will be shown on the output.
- Benchmark* Complexity(BigO complexity = benchmark::oAuto);
-
- // Set the asymptotic computational complexity for the benchmark. If called
- // the asymptotic computational complexity will be shown on the output.
- Benchmark* Complexity(BigOFunc* complexity);
-
- // Add this statistics to be computed over all the values of benchmark run
- Benchmark* ComputeStatistics(std::string name, StatisticsFunc* statistics);
-
- // Support for running multiple copies of the same benchmark concurrently
- // in multiple threads. This may be useful when measuring the scaling
- // of some piece of code.
-
- // Run one instance of this benchmark concurrently in t threads.
- Benchmark* Threads(int t);
-
- // Pick a set of values T from [min_threads,max_threads].
- // min_threads and max_threads are always included in T. Run this
- // benchmark once for each value in T. The benchmark run for a
- // particular value t consists of t threads running the benchmark
- // function concurrently. For example, consider:
- // BENCHMARK(Foo)->ThreadRange(1,16);
- // This will run the following benchmarks:
- // Foo in 1 thread
- // Foo in 2 threads
- // Foo in 4 threads
- // Foo in 8 threads
- // Foo in 16 threads
- Benchmark* ThreadRange(int min_threads, int max_threads);
-
- // For each value n in the range, run this benchmark once using n threads.
- // min_threads and max_threads are always included in the range.
- // stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts
- // a benchmark with 1, 4, 7 and 8 threads.
- Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1);
-
- // Equivalent to ThreadRange(NumCPUs(), NumCPUs())
- Benchmark* ThreadPerCpu();
-
- virtual void Run(State& state) = 0;
-
- protected:
- explicit Benchmark(const char* name);
- Benchmark(Benchmark const&);
- void SetName(const char* name);
-
- int ArgsCnt() const;
-
- private:
- friend class BenchmarkFamilies;
-
- std::string name_;
- AggregationReportMode aggregation_report_mode_;
- std::vector<std::string> arg_names_; // Args for all benchmark runs
- std::vector<std::vector<int64_t> > args_; // Args for all benchmark runs
- TimeUnit time_unit_;
- int range_multiplier_;
- double min_time_;
- IterationCount iterations_;
- int repetitions_;
- bool measure_process_cpu_time_;
- bool use_real_time_;
- bool use_manual_time_;
- BigO complexity_;
- BigOFunc* complexity_lambda_;
- std::vector<Statistics> statistics_;
- std::vector<int> thread_counts_;
-
- Benchmark& operator=(Benchmark const&);
-};
-
-} // namespace internal
-
-// Create and register a benchmark with the specified 'name' that invokes
-// the specified functor 'fn'.
-//
-// RETURNS: A pointer to the registered benchmark.
-internal::Benchmark* RegisterBenchmark(const char* name,
- internal::Function* fn);
-
-#if defined(BENCHMARK_HAS_CXX11)
-template <class Lambda>
-internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn);
-#endif
-
-// Remove all registered benchmarks. All pointers to previously registered
-// benchmarks are invalidated.
-void ClearRegisteredBenchmarks();
-
-namespace internal {
-// The class used to hold all Benchmarks created from static function.
-// (ie those created using the BENCHMARK(...) macros.
-class FunctionBenchmark : public Benchmark {
- public:
- FunctionBenchmark(const char* name, Function* func)
- : Benchmark(name), func_(func) {}
-
- virtual void Run(State& st);
-
- private:
- Function* func_;
-};
-
-#ifdef BENCHMARK_HAS_CXX11
-template <class Lambda>
-class LambdaBenchmark : public Benchmark {
- public:
- virtual void Run(State& st) { lambda_(st); }
-
- private:
- template <class OLambda>
- LambdaBenchmark(const char* name, OLambda&& lam)
- : Benchmark(name), lambda_(std::forward<OLambda>(lam)) {}
-
- LambdaBenchmark(LambdaBenchmark const&) = delete;
-
- private:
- template <class Lam>
- friend Benchmark* ::benchmark::RegisterBenchmark(const char*, Lam&&);
-
- Lambda lambda_;
-};
-#endif
-
-} // namespace internal
-
-inline internal::Benchmark* RegisterBenchmark(const char* name,
- internal::Function* fn) {
- return internal::RegisterBenchmarkInternal(
- ::new internal::FunctionBenchmark(name, fn));
-}
-
-#ifdef BENCHMARK_HAS_CXX11
-template <class Lambda>
-internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn) {
- using BenchType =
- internal::LambdaBenchmark<typename std::decay<Lambda>::type>;
- return internal::RegisterBenchmarkInternal(
- ::new BenchType(name, std::forward<Lambda>(fn)));
-}
-#endif
-
-#if defined(BENCHMARK_HAS_CXX11) && \
- (!defined(BENCHMARK_GCC_VERSION) || BENCHMARK_GCC_VERSION >= 409)
-template <class Lambda, class... Args>
-internal::Benchmark* RegisterBenchmark(const char* name, Lambda&& fn,
- Args&&... args) {
- return benchmark::RegisterBenchmark(
- name, [=](benchmark::State& st) { fn(st, args...); });
-}
-#else
-#define BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
-#endif
-
-// The base class for all fixture tests.
-class Fixture : public internal::Benchmark {
- public:
- Fixture() : internal::Benchmark("") {}
-
- virtual void Run(State& st) {
- this->SetUp(st);
- this->BenchmarkCase(st);
- this->TearDown(st);
- }
-
- // These will be deprecated ...
- virtual void SetUp(const State&) {}
- virtual void TearDown(const State&) {}
- // ... In favor of these.
- virtual void SetUp(State& st) { SetUp(const_cast<const State&>(st)); }
- virtual void TearDown(State& st) { TearDown(const_cast<const State&>(st)); }
-
- protected:
- virtual void BenchmarkCase(State&) = 0;
-};
-
-} // namespace benchmark
-
-// ------------------------------------------------------
-// Macro to register benchmarks
-
-// Check that __COUNTER__ is defined and that __COUNTER__ increases by 1
-// every time it is expanded. X + 1 == X + 0 is used in case X is defined to be
-// empty. If X is empty the expression becomes (+1 == +0).
-#if defined(__COUNTER__) && (__COUNTER__ + 1 == __COUNTER__ + 0)
-#define BENCHMARK_PRIVATE_UNIQUE_ID __COUNTER__
-#else
-#define BENCHMARK_PRIVATE_UNIQUE_ID __LINE__
-#endif
-
-// Helpers for generating unique variable names
-#define BENCHMARK_PRIVATE_NAME(n) \
- BENCHMARK_PRIVATE_CONCAT(_benchmark_, BENCHMARK_PRIVATE_UNIQUE_ID, n)
-#define BENCHMARK_PRIVATE_CONCAT(a, b, c) BENCHMARK_PRIVATE_CONCAT2(a, b, c)
-#define BENCHMARK_PRIVATE_CONCAT2(a, b, c) a##b##c
-
-#define BENCHMARK_PRIVATE_DECLARE(n) \
- static ::benchmark::internal::Benchmark* BENCHMARK_PRIVATE_NAME(n) \
- BENCHMARK_UNUSED
-
-#define BENCHMARK(n) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- new ::benchmark::internal::FunctionBenchmark(#n, n)))
-
-// Old-style macros
-#define BENCHMARK_WITH_ARG(n, a) BENCHMARK(n)->Arg((a))
-#define BENCHMARK_WITH_ARG2(n, a1, a2) BENCHMARK(n)->Args({(a1), (a2)})
-#define BENCHMARK_WITH_UNIT(n, t) BENCHMARK(n)->Unit((t))
-#define BENCHMARK_RANGE(n, lo, hi) BENCHMARK(n)->Range((lo), (hi))
-#define BENCHMARK_RANGE2(n, l1, h1, l2, h2) \
- BENCHMARK(n)->RangePair({{(l1), (h1)}, {(l2), (h2)}})
-
-#ifdef BENCHMARK_HAS_CXX11
-
-// Register a benchmark which invokes the function specified by `func`
-// with the additional arguments specified by `...`.
-//
-// For example:
-//
-// template <class ...ExtraArgs>`
-// void BM_takes_args(benchmark::State& state, ExtraArgs&&... extra_args) {
-// [...]
-//}
-// /* Registers a benchmark named "BM_takes_args/int_string_test` */
-// BENCHMARK_CAPTURE(BM_takes_args, int_string_test, 42, std::string("abc"));
-#define BENCHMARK_CAPTURE(func, test_case_name, ...) \
- BENCHMARK_PRIVATE_DECLARE(func) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- new ::benchmark::internal::FunctionBenchmark( \
- #func "/" #test_case_name, \
- [](::benchmark::State& st) { func(st, __VA_ARGS__); })))
-
-#endif // BENCHMARK_HAS_CXX11
-
-// This will register a benchmark for a templatized function. For example:
-//
-// template<int arg>
-// void BM_Foo(int iters);
-//
-// BENCHMARK_TEMPLATE(BM_Foo, 1);
-//
-// will register BM_Foo<1> as a benchmark.
-#define BENCHMARK_TEMPLATE1(n, a) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))
-
-#define BENCHMARK_TEMPLATE2(n, a, b) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- new ::benchmark::internal::FunctionBenchmark(#n "<" #a "," #b ">", \
- n<a, b>)))
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE(n, ...) \
- BENCHMARK_PRIVATE_DECLARE(n) = \
- (::benchmark::internal::RegisterBenchmarkInternal( \
- new ::benchmark::internal::FunctionBenchmark( \
- #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))
-#else
-#define BENCHMARK_TEMPLATE(n, a) BENCHMARK_TEMPLATE1(n, a)
-#endif
-
-#define BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
- class BaseClass##_##Method##_Benchmark : public BaseClass { \
- public: \
- BaseClass##_##Method##_Benchmark() : BaseClass() { \
- this->SetName(#BaseClass "/" #Method); \
- } \
- \
- protected: \
- virtual void BenchmarkCase(::benchmark::State&); \
- };
-
-#define BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
- class BaseClass##_##Method##_Benchmark : public BaseClass<a> { \
- public: \
- BaseClass##_##Method##_Benchmark() : BaseClass<a>() { \
- this->SetName(#BaseClass "<" #a ">/" #Method); \
- } \
- \
- protected: \
- virtual void BenchmarkCase(::benchmark::State&); \
- };
-
-#define BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
- class BaseClass##_##Method##_Benchmark : public BaseClass<a, b> { \
- public: \
- BaseClass##_##Method##_Benchmark() : BaseClass<a, b>() { \
- this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \
- } \
- \
- protected: \
- virtual void BenchmarkCase(::benchmark::State&); \
- };
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, ...) \
- class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \
- public: \
- BaseClass##_##Method##_Benchmark() : BaseClass<__VA_ARGS__>() { \
- this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); \
- } \
- \
- protected: \
- virtual void BenchmarkCase(::benchmark::State&); \
- };
-#else
-#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(n, a) \
- BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(n, a)
-#endif
-
-#define BENCHMARK_DEFINE_F(BaseClass, Method) \
- BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) \
- BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE2_DEFINE_F(BaseClass, Method, a, b) \
- BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, ...) \
- BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-#else
-#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, a) \
- BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a)
-#endif
-
-#define BENCHMARK_REGISTER_F(BaseClass, Method) \
- BENCHMARK_PRIVATE_REGISTER_F(BaseClass##_##Method##_Benchmark)
-
-#define BENCHMARK_PRIVATE_REGISTER_F(TestName) \
- BENCHMARK_PRIVATE_DECLARE(TestName) = \
- (::benchmark::internal::RegisterBenchmarkInternal(new TestName()))
-
-// This macro will define and register a benchmark within a fixture class.
-#define BENCHMARK_F(BaseClass, Method) \
- BENCHMARK_PRIVATE_DECLARE_F(BaseClass, Method) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) \
- BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(BaseClass, Method, a) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-
-#define BENCHMARK_TEMPLATE2_F(BaseClass, Method, a, b) \
- BENCHMARK_TEMPLATE2_PRIVATE_DECLARE_F(BaseClass, Method, a, b) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-
-#ifdef BENCHMARK_HAS_CXX11
-#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \
- BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \
- BENCHMARK_REGISTER_F(BaseClass, Method); \
- void BaseClass##_##Method##_Benchmark::BenchmarkCase
-#else
-#define BENCHMARK_TEMPLATE_F(BaseClass, Method, a) \
- BENCHMARK_TEMPLATE1_F(BaseClass, Method, a)
-#endif
-
-// Helper macro to create a main routine in a test that runs the benchmarks
-#define BENCHMARK_MAIN() \
- int main(int argc, char** argv) { \
- ::benchmark::Initialize(&argc, argv); \
- if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \
- ::benchmark::RunSpecifiedBenchmarks(); \
- } \
- int main(int, char**)
-
-// ------------------------------------------------------
-// Benchmark Reporters
-
-namespace benchmark {
-
-struct CPUInfo {
- struct CacheInfo {
- std::string type;
- int level;
- int size;
- int num_sharing;
- };
-
- int num_cpus;
- double cycles_per_second;
- std::vector<CacheInfo> caches;
- bool scaling_enabled;
- std::vector<double> load_avg;
-
- static const CPUInfo& Get();
-
- private:
- CPUInfo();
- BENCHMARK_DISALLOW_COPY_AND_ASSIGN(CPUInfo);
-};
-
-// Adding Struct for System Information
-struct SystemInfo {
- std::string name;
- static const SystemInfo& Get();
-
- private:
- SystemInfo();
- BENCHMARK_DISALLOW_COPY_AND_ASSIGN(SystemInfo);
-};
-
-// BenchmarkName contains the components of the Benchmark's name
-// which allows individual fields to be modified or cleared before
-// building the final name using 'str()'.
-struct BenchmarkName {
- std::string function_name;
- std::string args;
- std::string min_time;
- std::string iterations;
- std::string repetitions;
- std::string time_type;
- std::string threads;
-
- // Return the full name of the benchmark with each non-empty
- // field separated by a '/'
- std::string str() const;
-};
-
-// Interface for custom benchmark result printers.
-// By default, benchmark reports are printed to stdout. However an application
-// can control the destination of the reports by calling
-// RunSpecifiedBenchmarks and passing it a custom reporter object.
-// The reporter object must implement the following interface.
-class BenchmarkReporter {
- public:
- struct Context {
- CPUInfo const& cpu_info;
- SystemInfo const& sys_info;
- // The number of chars in the longest benchmark name.
- size_t name_field_width;
- static const char* executable_name;
- Context();
- };
-
- struct Run {
- static const int64_t no_repetition_index = -1;
- enum RunType { RT_Iteration, RT_Aggregate };
-
- Run()
- : run_type(RT_Iteration),
- error_occurred(false),
- iterations(1),
- threads(1),
- time_unit(kNanosecond),
- real_accumulated_time(0),
- cpu_accumulated_time(0),
- max_heapbytes_used(0),
- complexity(oNone),
- complexity_lambda(),
- complexity_n(0),
- report_big_o(false),
- report_rms(false),
- counters(),
- has_memory_result(false),
- allocs_per_iter(0.0),
- max_bytes_used(0) {}
-
- std::string benchmark_name() const;
- BenchmarkName run_name;
- RunType run_type;
- std::string aggregate_name;
- std::string report_label; // Empty if not set by benchmark.
- bool error_occurred;
- std::string error_message;
-
- IterationCount iterations;
- int64_t threads;
- int64_t repetition_index;
- int64_t repetitions;
- TimeUnit time_unit;
- double real_accumulated_time;
- double cpu_accumulated_time;
-
- // Return a value representing the real time per iteration in the unit
- // specified by 'time_unit'.
- // NOTE: If 'iterations' is zero the returned value represents the
- // accumulated time.
- double GetAdjustedRealTime() const;
-
- // Return a value representing the cpu time per iteration in the unit
- // specified by 'time_unit'.
- // NOTE: If 'iterations' is zero the returned value represents the
- // accumulated time.
- double GetAdjustedCPUTime() const;
-
- // This is set to 0.0 if memory tracing is not enabled.
- double max_heapbytes_used;
-
- // Keep track of arguments to compute asymptotic complexity
- BigO complexity;
- BigOFunc* complexity_lambda;
- int64_t complexity_n;
-
- // what statistics to compute from the measurements
- const std::vector<internal::Statistics>* statistics;
-
- // Inform print function whether the current run is a complexity report
- bool report_big_o;
- bool report_rms;
-
- UserCounters counters;
-
- // Memory metrics.
- bool has_memory_result;
- double allocs_per_iter;
- int64_t max_bytes_used;
- };
-
- // Construct a BenchmarkReporter with the output stream set to 'std::cout'
- // and the error stream set to 'std::cerr'
- BenchmarkReporter();
-
- // Called once for every suite of benchmarks run.
- // The parameter "context" contains information that the
- // reporter may wish to use when generating its report, for example the
- // platform under which the benchmarks are running. The benchmark run is
- // never started if this function returns false, allowing the reporter
- // to skip runs based on the context information.
- virtual bool ReportContext(const Context& context) = 0;
-
- // Called once for each group of benchmark runs, gives information about
- // cpu-time and heap memory usage during the benchmark run. If the group
- // of runs contained more than two entries then 'report' contains additional
- // elements representing the mean and standard deviation of those runs.
- // Additionally if this group of runs was the last in a family of benchmarks
- // 'reports' contains additional entries representing the asymptotic
- // complexity and RMS of that benchmark family.
- virtual void ReportRuns(const std::vector<Run>& report) = 0;
-
- // Called once and only once after ever group of benchmarks is run and
- // reported.
- virtual void Finalize() {}
-
- // REQUIRES: The object referenced by 'out' is valid for the lifetime
- // of the reporter.
- void SetOutputStream(std::ostream* out) {
- assert(out);
- output_stream_ = out;
- }
-
- // REQUIRES: The object referenced by 'err' is valid for the lifetime
- // of the reporter.
- void SetErrorStream(std::ostream* err) {
- assert(err);
- error_stream_ = err;
- }
-
- std::ostream& GetOutputStream() const { return *output_stream_; }
-
- std::ostream& GetErrorStream() const { return *error_stream_; }
-
- virtual ~BenchmarkReporter();
-
- // Write a human readable string to 'out' representing the specified
- // 'context'.
- // REQUIRES: 'out' is non-null.
- static void PrintBasicContext(std::ostream* out, Context const& context);
-
- private:
- std::ostream* output_stream_;
- std::ostream* error_stream_;
-};
-
-// Simple reporter that outputs benchmark data to the console. This is the
-// default reporter used by RunSpecifiedBenchmarks().
-class ConsoleReporter : public BenchmarkReporter {
- public:
- enum OutputOptions {
- OO_None = 0,
- OO_Color = 1,
- OO_Tabular = 2,
- OO_ColorTabular = OO_Color | OO_Tabular,
- OO_Defaults = OO_ColorTabular
- };
- explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults)
- : output_options_(opts_),
- name_field_width_(0),
- prev_counters_(),
- printed_header_(false) {}
-
- virtual bool ReportContext(const Context& context);
- virtual void ReportRuns(const std::vector<Run>& reports);
-
- protected:
- virtual void PrintRunData(const Run& report);
- virtual void PrintHeader(const Run& report);
-
- OutputOptions output_options_;
- size_t name_field_width_;
- UserCounters prev_counters_;
- bool printed_header_;
-};
-
-class JSONReporter : public BenchmarkReporter {
- public:
- JSONReporter() : first_report_(true) {}
- virtual bool ReportContext(const Context& context);
- virtual void ReportRuns(const std::vector<Run>& reports);
- virtual void Finalize();
-
- private:
- void PrintRunData(const Run& report);
-
- bool first_report_;
-};
-
-class BENCHMARK_DEPRECATED_MSG(
- "The CSV Reporter will be removed in a future release") CSVReporter
- : public BenchmarkReporter {
- public:
- CSVReporter() : printed_header_(false) {}
- virtual bool ReportContext(const Context& context);
- virtual void ReportRuns(const std::vector<Run>& reports);
-
- private:
- void PrintRunData(const Run& report);
-
- bool printed_header_;
- std::set<std::string> user_counter_names_;
-};
-
-// If a MemoryManager is registered, it can be used to collect and report
-// allocation metrics for a run of the benchmark.
-class MemoryManager {
- public:
- struct Result {
- Result() : num_allocs(0), max_bytes_used(0) {}
-
- // The number of allocations made in total between Start and Stop.
- int64_t num_allocs;
-
- // The peak memory use between Start and Stop.
- int64_t max_bytes_used;
- };
-
- virtual ~MemoryManager() {}
-
- // Implement this to start recording allocation information.
- virtual void Start() = 0;
-
- // Implement this to stop recording and fill out the given Result structure.
- virtual void Stop(Result* result) = 0;
-};
-
-inline const char* GetTimeUnitString(TimeUnit unit) {
- switch (unit) {
- case kMillisecond:
- return "ms";
- case kMicrosecond:
- return "us";
- case kNanosecond:
- return "ns";
- }
- BENCHMARK_UNREACHABLE();
-}
-
-inline double GetTimeUnitMultiplier(TimeUnit unit) {
- switch (unit) {
- case kMillisecond:
- return 1e3;
- case kMicrosecond:
- return 1e6;
- case kNanosecond:
- return 1e9;
- }
- BENCHMARK_UNREACHABLE();
-}
-
-} // namespace benchmark
-
-#endif // BENCHMARK_BENCHMARK_H_
+++ /dev/null
-#! /usr/bin/env python
-# encoding: utf-8
-
-import argparse
-import errno
-import logging
-import os
-import platform
-import re
-import sys
-import subprocess
-import tempfile
-
-try:
- import winreg
-except ImportError:
- import _winreg as winreg
-try:
- import urllib.request as request
-except ImportError:
- import urllib as request
-try:
- import urllib.parse as parse
-except ImportError:
- import urlparse as parse
-
-class EmptyLogger(object):
- '''
- Provides an implementation that performs no logging
- '''
- def debug(self, *k, **kw):
- pass
- def info(self, *k, **kw):
- pass
- def warn(self, *k, **kw):
- pass
- def error(self, *k, **kw):
- pass
- def critical(self, *k, **kw):
- pass
- def setLevel(self, *k, **kw):
- pass
-
-urls = (
- 'http://downloads.sourceforge.net/project/mingw-w64/Toolchains%20'
- 'targetting%20Win32/Personal%20Builds/mingw-builds/installer/'
- 'repository.txt',
- 'http://downloads.sourceforge.net/project/mingwbuilds/host-windows/'
- 'repository.txt'
-)
-'''
-A list of mingw-build repositories
-'''
-
-def repository(urls = urls, log = EmptyLogger()):
- '''
- Downloads and parse mingw-build repository files and parses them
- '''
- log.info('getting mingw-builds repository')
- versions = {}
- re_sourceforge = re.compile(r'http://sourceforge.net/projects/([^/]+)/files')
- re_sub = r'http://downloads.sourceforge.net/project/\1'
- for url in urls:
- log.debug(' - requesting: %s', url)
- socket = request.urlopen(url)
- repo = socket.read()
- if not isinstance(repo, str):
- repo = repo.decode();
- socket.close()
- for entry in repo.split('\n')[:-1]:
- value = entry.split('|')
- version = tuple([int(n) for n in value[0].strip().split('.')])
- version = versions.setdefault(version, {})
- arch = value[1].strip()
- if arch == 'x32':
- arch = 'i686'
- elif arch == 'x64':
- arch = 'x86_64'
- arch = version.setdefault(arch, {})
- threading = arch.setdefault(value[2].strip(), {})
- exceptions = threading.setdefault(value[3].strip(), {})
- revision = exceptions.setdefault(int(value[4].strip()[3:]),
- re_sourceforge.sub(re_sub, value[5].strip()))
- return versions
-
-def find_in_path(file, path=None):
- '''
- Attempts to find an executable in the path
- '''
- if platform.system() == 'Windows':
- file += '.exe'
- if path is None:
- path = os.environ.get('PATH', '')
- if type(path) is type(''):
- path = path.split(os.pathsep)
- return list(filter(os.path.exists,
- map(lambda dir, file=file: os.path.join(dir, file), path)))
-
-def find_7zip(log = EmptyLogger()):
- '''
- Attempts to find 7zip for unpacking the mingw-build archives
- '''
- log.info('finding 7zip')
- path = find_in_path('7z')
- if not path:
- key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\7-Zip')
- path, _ = winreg.QueryValueEx(key, 'Path')
- path = [os.path.join(path, '7z.exe')]
- log.debug('found \'%s\'', path[0])
- return path[0]
-
-find_7zip()
-
-def unpack(archive, location, log = EmptyLogger()):
- '''
- Unpacks a mingw-builds archive
- '''
- sevenzip = find_7zip(log)
- log.info('unpacking %s', os.path.basename(archive))
- cmd = [sevenzip, 'x', archive, '-o' + location, '-y']
- log.debug(' - %r', cmd)
- with open(os.devnull, 'w') as devnull:
- subprocess.check_call(cmd, stdout = devnull)
-
-def download(url, location, log = EmptyLogger()):
- '''
- Downloads and unpacks a mingw-builds archive
- '''
- log.info('downloading MinGW')
- log.debug(' - url: %s', url)
- log.debug(' - location: %s', location)
-
- re_content = re.compile(r'attachment;[ \t]*filename=(")?([^"]*)(")?[\r\n]*')
-
- stream = request.urlopen(url)
- try:
- content = stream.getheader('Content-Disposition') or ''
- except AttributeError:
- content = stream.headers.getheader('Content-Disposition') or ''
- matches = re_content.match(content)
- if matches:
- filename = matches.group(2)
- else:
- parsed = parse.urlparse(stream.geturl())
- filename = os.path.basename(parsed.path)
-
- try:
- os.makedirs(location)
- except OSError as e:
- if e.errno == errno.EEXIST and os.path.isdir(location):
- pass
- else:
- raise
-
- archive = os.path.join(location, filename)
- with open(archive, 'wb') as out:
- while True:
- buf = stream.read(1024)
- if not buf:
- break
- out.write(buf)
- unpack(archive, location, log = log)
- os.remove(archive)
-
- possible = os.path.join(location, 'mingw64')
- if not os.path.exists(possible):
- possible = os.path.join(location, 'mingw32')
- if not os.path.exists(possible):
- raise ValueError('Failed to find unpacked MinGW: ' + possible)
- return possible
-
-def root(location = None, arch = None, version = None, threading = None,
- exceptions = None, revision = None, log = EmptyLogger()):
- '''
- Returns the root folder of a specific version of the mingw-builds variant
- of gcc. Will download the compiler if needed
- '''
-
- # Get the repository if we don't have all the information
- if not (arch and version and threading and exceptions and revision):
- versions = repository(log = log)
-
- # Determine some defaults
- version = version or max(versions.keys())
- if not arch:
- arch = platform.machine().lower()
- if arch == 'x86':
- arch = 'i686'
- elif arch == 'amd64':
- arch = 'x86_64'
- if not threading:
- keys = versions[version][arch].keys()
- if 'posix' in keys:
- threading = 'posix'
- elif 'win32' in keys:
- threading = 'win32'
- else:
- threading = keys[0]
- if not exceptions:
- keys = versions[version][arch][threading].keys()
- if 'seh' in keys:
- exceptions = 'seh'
- elif 'sjlj' in keys:
- exceptions = 'sjlj'
- else:
- exceptions = keys[0]
- if revision is None:
- revision = max(versions[version][arch][threading][exceptions].keys())
- if not location:
- location = os.path.join(tempfile.gettempdir(), 'mingw-builds')
-
- # Get the download url
- url = versions[version][arch][threading][exceptions][revision]
-
- # Tell the user whatzzup
- log.info('finding MinGW %s', '.'.join(str(v) for v in version))
- log.debug(' - arch: %s', arch)
- log.debug(' - threading: %s', threading)
- log.debug(' - exceptions: %s', exceptions)
- log.debug(' - revision: %s', revision)
- log.debug(' - url: %s', url)
-
- # Store each specific revision differently
- slug = '{version}-{arch}-{threading}-{exceptions}-rev{revision}'
- slug = slug.format(
- version = '.'.join(str(v) for v in version),
- arch = arch,
- threading = threading,
- exceptions = exceptions,
- revision = revision
- )
- if arch == 'x86_64':
- root_dir = os.path.join(location, slug, 'mingw64')
- elif arch == 'i686':
- root_dir = os.path.join(location, slug, 'mingw32')
- else:
- raise ValueError('Unknown MinGW arch: ' + arch)
-
- # Download if needed
- if not os.path.exists(root_dir):
- downloaded = download(url, os.path.join(location, slug), log = log)
- if downloaded != root_dir:
- raise ValueError('The location of mingw did not match\n%s\n%s'
- % (downloaded, root_dir))
-
- return root_dir
-
-def str2ver(string):
- '''
- Converts a version string into a tuple
- '''
- try:
- version = tuple(int(v) for v in string.split('.'))
- if len(version) is not 3:
- raise ValueError()
- except ValueError:
- raise argparse.ArgumentTypeError(
- 'please provide a three digit version string')
- return version
-
-def main():
- '''
- Invoked when the script is run directly by the python interpreter
- '''
- parser = argparse.ArgumentParser(
- description = 'Downloads a specific version of MinGW',
- formatter_class = argparse.ArgumentDefaultsHelpFormatter
- )
- parser.add_argument('--location',
- help = 'the location to download the compiler to',
- default = os.path.join(tempfile.gettempdir(), 'mingw-builds'))
- parser.add_argument('--arch', required = True, choices = ['i686', 'x86_64'],
- help = 'the target MinGW architecture string')
- parser.add_argument('--version', type = str2ver,
- help = 'the version of GCC to download')
- parser.add_argument('--threading', choices = ['posix', 'win32'],
- help = 'the threading type of the compiler')
- parser.add_argument('--exceptions', choices = ['sjlj', 'seh', 'dwarf'],
- help = 'the method to throw exceptions')
- parser.add_argument('--revision', type=int,
- help = 'the revision of the MinGW release')
- group = parser.add_mutually_exclusive_group()
- group.add_argument('-v', '--verbose', action='store_true',
- help='increase the script output verbosity')
- group.add_argument('-q', '--quiet', action='store_true',
- help='only print errors and warning')
- args = parser.parse_args()
-
- # Create the logger
- logger = logging.getLogger('mingw')
- handler = logging.StreamHandler()
- formatter = logging.Formatter('%(message)s')
- handler.setFormatter(formatter)
- logger.addHandler(handler)
- logger.setLevel(logging.INFO)
- if args.quiet:
- logger.setLevel(logging.WARN)
- if args.verbose:
- logger.setLevel(logging.DEBUG)
-
- # Get MinGW
- root_dir = root(location = args.location, arch = args.arch,
- version = args.version, threading = args.threading,
- exceptions = args.exceptions, revision = args.revision,
- log = logger)
-
- sys.stdout.write('%s\n' % os.path.join(root_dir, 'bin'))
-
-if __name__ == '__main__':
- try:
- main()
- except IOError as e:
- sys.stderr.write('IO error: %s\n' % e)
- sys.exit(1)
- except OSError as e:
- sys.stderr.write('OS error: %s\n' % e)
- sys.exit(1)
- except KeyboardInterrupt as e:
- sys.stderr.write('Killed\n')
- sys.exit(1)
+++ /dev/null
-# How to release
-
-* Make sure you're on master and synced to HEAD
-* Ensure the project builds and tests run (sanity check only, obviously)
- * `parallel -j0 exec ::: test/*_test` can help ensure everything at least
- passes
-* Prepare release notes
- * `git log $(git describe --abbrev=0 --tags)..HEAD` gives you the list of
- commits between the last annotated tag and HEAD
- * Pick the most interesting.
-* Create a release through github's interface
- * Note this will create a lightweight tag.
- * Update this to an annotated tag:
- * `git pull --tags`
- * `git tag -a -f <tag> <tag>`
- * `git push --force origin`
+++ /dev/null
-import os
-import posixpath
-import re
-import shutil
-import sys
-
-from distutils import sysconfig
-import setuptools
-from setuptools.command import build_ext
-
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-
-IS_WINDOWS = sys.platform.startswith('win')
-
-
-def _get_version():
- """Parse the version string from __init__.py."""
- with open(os.path.join(here, 'bindings', 'python', 'benchmark', '__init__.py')) as f:
- try:
- version_line = next(
- line for line in f if line.startswith('__version__'))
- except StopIteration:
- raise ValueError('__version__ not defined in __init__.py')
- else:
- ns = {}
- exec(version_line, ns) # pylint: disable=exec-used
- return ns['__version__']
-
-
-def _parse_requirements(path):
- with open(os.path.join(here, path)) as f:
- return [
- line.rstrip() for line in f
- if not (line.isspace() or line.startswith('#'))
- ]
-
-
-class BazelExtension(setuptools.Extension):
- """A C/C++ extension that is defined as a Bazel BUILD target."""
-
- def __init__(self, name, bazel_target):
- self.bazel_target = bazel_target
- self.relpath, self.target_name = (
- posixpath.relpath(bazel_target, '//').split(':'))
- setuptools.Extension.__init__(self, name, sources=[])
-
-
-class BuildBazelExtension(build_ext.build_ext):
- """A command that runs Bazel to build a C/C++ extension."""
-
- def run(self):
- for ext in self.extensions:
- self.bazel_build(ext)
- build_ext.build_ext.run(self)
-
- def bazel_build(self, ext):
- with open('WORKSPACE', 'r') as f:
- workspace_contents = f.read()
-
- with open('WORKSPACE', 'w') as f:
- f.write(re.sub(
- r'(?<=path = ").*(?=", # May be overwritten by setup\.py\.)',
- sysconfig.get_python_inc().replace(os.path.sep, posixpath.sep),
- workspace_contents))
-
- if not os.path.exists(self.build_temp):
- os.makedirs(self.build_temp)
-
- bazel_argv = [
- 'bazel',
- 'build',
- ext.bazel_target,
- '--symlink_prefix=' + os.path.join(self.build_temp, 'bazel-'),
- '--compilation_mode=' + ('dbg' if self.debug else 'opt'),
- ]
-
- if IS_WINDOWS:
- # Link with python*.lib.
- for library_dir in self.library_dirs:
- bazel_argv.append('--linkopt=/LIBPATH:' + library_dir)
-
- self.spawn(bazel_argv)
-
- shared_lib_suffix = '.dll' if IS_WINDOWS else '.so'
- ext_bazel_bin_path = os.path.join(
- self.build_temp, 'bazel-bin',
- ext.relpath, ext.target_name + shared_lib_suffix)
- ext_dest_path = self.get_ext_fullpath(ext.name)
- ext_dest_dir = os.path.dirname(ext_dest_path)
- if not os.path.exists(ext_dest_dir):
- os.makedirs(ext_dest_dir)
- shutil.copyfile(ext_bazel_bin_path, ext_dest_path)
-
-
-setuptools.setup(
- name='google-benchmark',
- version=_get_version(),
- url='https://github.com/google/benchmark',
- description='A library to benchmark code snippets.',
- author='Google',
- author_email='benchmark-py@google.com',
- # Contained modules and scripts.
- package_dir={'': 'bindings/python'},
- packages=setuptools.find_packages('bindings/python'),
- install_requires=_parse_requirements('bindings/python/requirements.txt'),
- cmdclass=dict(build_ext=BuildBazelExtension),
- ext_modules=[BazelExtension('benchmark._benchmark', '//bindings/python/benchmark:_benchmark')],
- zip_safe=False,
- # PyPI package information.
- classifiers=[
- 'Development Status :: 4 - Beta',
- 'Intended Audience :: Developers',
- 'Intended Audience :: Science/Research',
- 'License :: OSI Approved :: Apache Software License',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.7',
- 'Topic :: Software Development :: Testing',
- 'Topic :: System :: Benchmark',
- ],
- license='Apache 2.0',
- keywords='benchmark',
-)
+++ /dev/null
-# Allow the source files to find headers in src/
-include(GNUInstallDirs)
-include_directories(${PROJECT_SOURCE_DIR}/src)
-
-if (DEFINED BENCHMARK_CXX_LINKER_FLAGS)
- list(APPEND CMAKE_SHARED_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
- list(APPEND CMAKE_MODULE_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
-endif()
-
-file(GLOB
- SOURCE_FILES
- *.cc
- ${PROJECT_SOURCE_DIR}/include/benchmark/*.h
- ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
-file(GLOB BENCHMARK_MAIN "benchmark_main.cc")
-foreach(item ${BENCHMARK_MAIN})
- list(REMOVE_ITEM SOURCE_FILES "${item}")
-endforeach()
-
-add_library(benchmark ${SOURCE_FILES})
-add_library(benchmark::benchmark ALIAS benchmark)
-set_target_properties(benchmark PROPERTIES
- OUTPUT_NAME "benchmark"
- VERSION ${GENERIC_LIB_VERSION}
- SOVERSION ${GENERIC_LIB_SOVERSION}
-)
-target_include_directories(benchmark PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
- )
-
-# Link threads.
-target_link_libraries(benchmark ${BENCHMARK_CXX_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
-find_library(LIBRT rt)
-if(LIBRT)
- target_link_libraries(benchmark ${LIBRT})
-endif()
-
-if(CMAKE_BUILD_TYPE)
- string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
-endif()
-if(NOT CMAKE_THREAD_LIBS_INIT AND "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE_UPPER}}" MATCHES ".*-fsanitize=[^ ]*address.*")
- message(WARNING "CMake's FindThreads.cmake did not fail, but CMAKE_THREAD_LIBS_INIT ended up being empty. This was fixed in https://github.com/Kitware/CMake/commit/d53317130e84898c5328c237186dbd995aaf1c12 Let's guess that -pthread is sufficient.")
- target_link_libraries(benchmark -pthread)
-endif()
-
-# We need extra libraries on Windows
-if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
- target_link_libraries(benchmark shlwapi)
-endif()
-
-# We need extra libraries on Solaris
-if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
- target_link_libraries(benchmark kstat)
-endif()
-
-# Benchmark main library
-add_library(benchmark_main "benchmark_main.cc")
-add_library(benchmark::benchmark_main ALIAS benchmark_main)
-set_target_properties(benchmark_main PROPERTIES
- OUTPUT_NAME "benchmark_main"
- VERSION ${GENERIC_LIB_VERSION}
- SOVERSION ${GENERIC_LIB_SOVERSION}
-)
-target_include_directories(benchmark PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
- )
-target_link_libraries(benchmark_main benchmark::benchmark)
-
-
-set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
-
-set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
-set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
-set(pkg_config "${generated_dir}/${PROJECT_NAME}.pc")
-set(targets_export_name "${PROJECT_NAME}Targets")
-
-set(namespace "${PROJECT_NAME}::")
-
-include(CMakePackageConfigHelpers)
-write_basic_package_version_file(
- "${version_config}" VERSION ${GENERIC_LIB_VERSION} COMPATIBILITY SameMajorVersion
-)
-
-configure_file("${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in" "${project_config}" @ONLY)
-configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}" @ONLY)
-
-if (BENCHMARK_ENABLE_INSTALL)
- # Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable)
- install(
- TARGETS benchmark benchmark_main
- EXPORT ${targets_export_name}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
- INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
- install(
- DIRECTORY "${PROJECT_SOURCE_DIR}/include/benchmark"
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
- FILES_MATCHING PATTERN "*.*h")
-
- install(
- FILES "${project_config}" "${version_config}"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
-
- install(
- FILES "${pkg_config}"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
-
- install(
- EXPORT "${targets_export_name}"
- NAMESPACE "${namespace}"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
-endif()
+++ /dev/null
-#ifndef BENCHMARK_ARRAYSIZE_H_
-#define BENCHMARK_ARRAYSIZE_H_
-
-#include "internal_macros.h"
-
-namespace benchmark {
-namespace internal {
-// The arraysize(arr) macro returns the # of elements in an array arr.
-// The expression is a compile-time constant, and therefore can be
-// used in defining new arrays, for example. If you use arraysize on
-// a pointer by mistake, you will get a compile-time error.
-//
-
-// This template function declaration is used in defining arraysize.
-// Note that the function doesn't need an implementation, as we only
-// use its type.
-template <typename T, size_t N>
-char (&ArraySizeHelper(T (&array)[N]))[N];
-
-// That gcc wants both of these prototypes seems mysterious. VC, for
-// its part, can't decide which to use (another mystery). Matching of
-// template overloads: the final frontier.
-#ifndef COMPILER_MSVC
-template <typename T, size_t N>
-char (&ArraySizeHelper(const T (&array)[N]))[N];
-#endif
-
-#define arraysize(array) (sizeof(::benchmark::internal::ArraySizeHelper(array)))
-
-} // end namespace internal
-} // end namespace benchmark
-
-#endif // BENCHMARK_ARRAYSIZE_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-#include "benchmark_api_internal.h"
-#include "benchmark_runner.h"
-#include "internal_macros.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#ifndef BENCHMARK_OS_FUCHSIA
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-
-#include <algorithm>
-#include <atomic>
-#include <condition_variable>
-#include <cstdio>
-#include <cstdlib>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <string>
-#include <thread>
-#include <utility>
-
-#include "check.h"
-#include "colorprint.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "counter.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "mutex.h"
-#include "re.h"
-#include "statistics.h"
-#include "string_util.h"
-#include "thread_manager.h"
-#include "thread_timer.h"
-
-// Print a list of benchmarks. This option overrides all other options.
-DEFINE_bool(benchmark_list_tests, false);
-
-// A regular expression that specifies the set of benchmarks to execute. If
-// this flag is empty, or if this flag is the string \"all\", all benchmarks
-// linked into the binary are run.
-DEFINE_string(benchmark_filter, ".");
-
-// Minimum number of seconds we should run benchmark before results are
-// considered significant. For cpu-time based tests, this is the lower bound
-// on the total cpu time used by all threads that make up the test. For
-// real-time based tests, this is the lower bound on the elapsed time of the
-// benchmark execution, regardless of number of threads.
-DEFINE_double(benchmark_min_time, 0.5);
-
-// The number of runs of each benchmark. If greater than 1, the mean and
-// standard deviation of the runs will be reported.
-DEFINE_int32(benchmark_repetitions, 1);
-
-// Report the result of each benchmark repetitions. When 'true' is specified
-// only the mean, standard deviation, and other statistics are reported for
-// repeated benchmarks. Affects all reporters.
-DEFINE_bool(benchmark_report_aggregates_only, false);
-
-// Display the result of each benchmark repetitions. When 'true' is specified
-// only the mean, standard deviation, and other statistics are displayed for
-// repeated benchmarks. Unlike benchmark_report_aggregates_only, only affects
-// the display reporter, but *NOT* file reporter, which will still contain
-// all the output.
-DEFINE_bool(benchmark_display_aggregates_only, false);
-
-// The format to use for console output.
-// Valid values are 'console', 'json', or 'csv'.
-DEFINE_string(benchmark_format, "console");
-
-// The format to use for file output.
-// Valid values are 'console', 'json', or 'csv'.
-DEFINE_string(benchmark_out_format, "json");
-
-// The file to write additional output to.
-DEFINE_string(benchmark_out, "");
-
-// Whether to use colors in the output. Valid values:
-// 'true'/'yes'/1, 'false'/'no'/0, and 'auto'. 'auto' means to use colors if
-// the output is being sent to a terminal and the TERM environment variable is
-// set to a terminal type that supports colors.
-DEFINE_string(benchmark_color, "auto");
-
-// Whether to use tabular format when printing user counters to the console.
-// Valid values: 'true'/'yes'/1, 'false'/'no'/0. Defaults to false.
-DEFINE_bool(benchmark_counters_tabular, false);
-
-// The level of verbose logging to output
-DEFINE_int32(v, 0);
-
-namespace benchmark {
-
-namespace internal {
-
-// FIXME: wouldn't LTO mess this up?
-void UseCharPointer(char const volatile*) {}
-
-} // namespace internal
-
-State::State(IterationCount max_iters, const std::vector<int64_t>& ranges,
- int thread_i, int n_threads, internal::ThreadTimer* timer,
- internal::ThreadManager* manager)
- : total_iterations_(0),
- batch_leftover_(0),
- max_iterations(max_iters),
- started_(false),
- finished_(false),
- error_occurred_(false),
- range_(ranges),
- complexity_n_(0),
- counters(),
- thread_index(thread_i),
- threads(n_threads),
- timer_(timer),
- manager_(manager) {
- CHECK(max_iterations != 0) << "At least one iteration must be run";
- CHECK_LT(thread_index, threads) << "thread_index must be less than threads";
-
- // Note: The use of offsetof below is technically undefined until C++17
- // because State is not a standard layout type. However, all compilers
- // currently provide well-defined behavior as an extension (which is
- // demonstrated since constexpr evaluation must diagnose all undefined
- // behavior). However, GCC and Clang also warn about this use of offsetof,
- // which must be suppressed.
-#if defined(__INTEL_COMPILER)
-#pragma warning push
-#pragma warning(disable : 1875)
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Winvalid-offsetof"
-#endif
- // Offset tests to ensure commonly accessed data is on the first cache line.
- const int cache_line_size = 64;
- static_assert(offsetof(State, error_occurred_) <=
- (cache_line_size - sizeof(error_occurred_)),
- "");
-#if defined(__INTEL_COMPILER)
-#pragma warning pop
-#elif defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-}
-
-void State::PauseTiming() {
- // Add in time accumulated so far
- CHECK(started_ && !finished_ && !error_occurred_);
- timer_->StopTimer();
-}
-
-void State::ResumeTiming() {
- CHECK(started_ && !finished_ && !error_occurred_);
- timer_->StartTimer();
-}
-
-void State::SkipWithError(const char* msg) {
- CHECK(msg);
- error_occurred_ = true;
- {
- MutexLock l(manager_->GetBenchmarkMutex());
- if (manager_->results.has_error_ == false) {
- manager_->results.error_message_ = msg;
- manager_->results.has_error_ = true;
- }
- }
- total_iterations_ = 0;
- if (timer_->running()) timer_->StopTimer();
-}
-
-void State::SetIterationTime(double seconds) {
- timer_->SetIterationTime(seconds);
-}
-
-void State::SetLabel(const char* label) {
- MutexLock l(manager_->GetBenchmarkMutex());
- manager_->results.report_label_ = label;
-}
-
-void State::StartKeepRunning() {
- CHECK(!started_ && !finished_);
- started_ = true;
- total_iterations_ = error_occurred_ ? 0 : max_iterations;
- manager_->StartStopBarrier();
- if (!error_occurred_) ResumeTiming();
-}
-
-void State::FinishKeepRunning() {
- CHECK(started_ && (!finished_ || error_occurred_));
- if (!error_occurred_) {
- PauseTiming();
- }
- // Total iterations has now wrapped around past 0. Fix this.
- total_iterations_ = 0;
- finished_ = true;
- manager_->StartStopBarrier();
-}
-
-namespace internal {
-namespace {
-
-void RunBenchmarks(const std::vector<BenchmarkInstance>& benchmarks,
- BenchmarkReporter* display_reporter,
- BenchmarkReporter* file_reporter) {
- // Note the file_reporter can be null.
- CHECK(display_reporter != nullptr);
-
- // Determine the width of the name field using a minimum width of 10.
- bool might_have_aggregates = FLAGS_benchmark_repetitions > 1;
- size_t name_field_width = 10;
- size_t stat_field_width = 0;
- for (const BenchmarkInstance& benchmark : benchmarks) {
- name_field_width =
- std::max<size_t>(name_field_width, benchmark.name.str().size());
- might_have_aggregates |= benchmark.repetitions > 1;
-
- for (const auto& Stat : *benchmark.statistics)
- stat_field_width = std::max<size_t>(stat_field_width, Stat.name_.size());
- }
- if (might_have_aggregates) name_field_width += 1 + stat_field_width;
-
- // Print header here
- BenchmarkReporter::Context context;
- context.name_field_width = name_field_width;
-
- // Keep track of running times of all instances of current benchmark
- std::vector<BenchmarkReporter::Run> complexity_reports;
-
- // We flush streams after invoking reporter methods that write to them. This
- // ensures users get timely updates even when streams are not line-buffered.
- auto flushStreams = [](BenchmarkReporter* reporter) {
- if (!reporter) return;
- std::flush(reporter->GetOutputStream());
- std::flush(reporter->GetErrorStream());
- };
-
- if (display_reporter->ReportContext(context) &&
- (!file_reporter || file_reporter->ReportContext(context))) {
- flushStreams(display_reporter);
- flushStreams(file_reporter);
-
- for (const auto& benchmark : benchmarks) {
- RunResults run_results = RunBenchmark(benchmark, &complexity_reports);
-
- auto report = [&run_results](BenchmarkReporter* reporter,
- bool report_aggregates_only) {
- assert(reporter);
- // If there are no aggregates, do output non-aggregates.
- report_aggregates_only &= !run_results.aggregates_only.empty();
- if (!report_aggregates_only)
- reporter->ReportRuns(run_results.non_aggregates);
- if (!run_results.aggregates_only.empty())
- reporter->ReportRuns(run_results.aggregates_only);
- };
-
- report(display_reporter, run_results.display_report_aggregates_only);
- if (file_reporter)
- report(file_reporter, run_results.file_report_aggregates_only);
-
- flushStreams(display_reporter);
- flushStreams(file_reporter);
- }
- }
- display_reporter->Finalize();
- if (file_reporter) file_reporter->Finalize();
- flushStreams(display_reporter);
- flushStreams(file_reporter);
-}
-
-// Disable deprecated warnings temporarily because we need to reference
-// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-
-std::unique_ptr<BenchmarkReporter> CreateReporter(
- std::string const& name, ConsoleReporter::OutputOptions output_opts) {
- typedef std::unique_ptr<BenchmarkReporter> PtrType;
- if (name == "console") {
- return PtrType(new ConsoleReporter(output_opts));
- } else if (name == "json") {
- return PtrType(new JSONReporter);
- } else if (name == "csv") {
- return PtrType(new CSVReporter);
- } else {
- std::cerr << "Unexpected format: '" << name << "'\n";
- std::exit(1);
- }
-}
-
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-} // end namespace
-
-bool IsZero(double n) {
- return std::abs(n) < std::numeric_limits<double>::epsilon();
-}
-
-ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) {
- int output_opts = ConsoleReporter::OO_Defaults;
- auto is_benchmark_color = [force_no_color]() -> bool {
- if (force_no_color) {
- return false;
- }
- if (FLAGS_benchmark_color == "auto") {
- return IsColorTerminal();
- }
- return IsTruthyFlagValue(FLAGS_benchmark_color);
- };
- if (is_benchmark_color()) {
- output_opts |= ConsoleReporter::OO_Color;
- } else {
- output_opts &= ~ConsoleReporter::OO_Color;
- }
- if (FLAGS_benchmark_counters_tabular) {
- output_opts |= ConsoleReporter::OO_Tabular;
- } else {
- output_opts &= ~ConsoleReporter::OO_Tabular;
- }
- return static_cast<ConsoleReporter::OutputOptions>(output_opts);
-}
-
-} // end namespace internal
-
-size_t RunSpecifiedBenchmarks() {
- return RunSpecifiedBenchmarks(nullptr, nullptr);
-}
-
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter) {
- return RunSpecifiedBenchmarks(display_reporter, nullptr);
-}
-
-size_t RunSpecifiedBenchmarks(BenchmarkReporter* display_reporter,
- BenchmarkReporter* file_reporter) {
- std::string spec = FLAGS_benchmark_filter;
- if (spec.empty() || spec == "all")
- spec = "."; // Regexp that matches all benchmarks
-
- // Setup the reporters
- std::ofstream output_file;
- std::unique_ptr<BenchmarkReporter> default_display_reporter;
- std::unique_ptr<BenchmarkReporter> default_file_reporter;
- if (!display_reporter) {
- default_display_reporter = internal::CreateReporter(
- FLAGS_benchmark_format, internal::GetOutputOptions());
- display_reporter = default_display_reporter.get();
- }
- auto& Out = display_reporter->GetOutputStream();
- auto& Err = display_reporter->GetErrorStream();
-
- std::string const& fname = FLAGS_benchmark_out;
- if (fname.empty() && file_reporter) {
- Err << "A custom file reporter was provided but "
- "--benchmark_out=<file> was not specified."
- << std::endl;
- std::exit(1);
- }
- if (!fname.empty()) {
- output_file.open(fname);
- if (!output_file.is_open()) {
- Err << "invalid file name: '" << fname << std::endl;
- std::exit(1);
- }
- if (!file_reporter) {
- default_file_reporter = internal::CreateReporter(
- FLAGS_benchmark_out_format, ConsoleReporter::OO_None);
- file_reporter = default_file_reporter.get();
- }
- file_reporter->SetOutputStream(&output_file);
- file_reporter->SetErrorStream(&output_file);
- }
-
- std::vector<internal::BenchmarkInstance> benchmarks;
- if (!FindBenchmarksInternal(spec, &benchmarks, &Err)) return 0;
-
- if (benchmarks.empty()) {
- Err << "Failed to match any benchmarks against regex: " << spec << "\n";
- return 0;
- }
-
- if (FLAGS_benchmark_list_tests) {
- for (auto const& benchmark : benchmarks)
- Out << benchmark.name.str() << "\n";
- } else {
- internal::RunBenchmarks(benchmarks, display_reporter, file_reporter);
- }
-
- return benchmarks.size();
-}
-
-void RegisterMemoryManager(MemoryManager* manager) {
- internal::memory_manager = manager;
-}
-
-namespace internal {
-
-void PrintUsageAndExit() {
- fprintf(stdout,
- "benchmark"
- " [--benchmark_list_tests={true|false}]\n"
- " [--benchmark_filter=<regex>]\n"
- " [--benchmark_min_time=<min_time>]\n"
- " [--benchmark_repetitions=<num_repetitions>]\n"
- " [--benchmark_report_aggregates_only={true|false}]\n"
- " [--benchmark_display_aggregates_only={true|false}]\n"
- " [--benchmark_format=<console|json|csv>]\n"
- " [--benchmark_out=<filename>]\n"
- " [--benchmark_out_format=<json|console|csv>]\n"
- " [--benchmark_color={auto|true|false}]\n"
- " [--benchmark_counters_tabular={true|false}]\n"
- " [--v=<verbosity>]\n");
- exit(0);
-}
-
-void ParseCommandLineFlags(int* argc, char** argv) {
- using namespace benchmark;
- BenchmarkReporter::Context::executable_name =
- (argc && *argc > 0) ? argv[0] : "unknown";
- for (int i = 1; argc && i < *argc; ++i) {
- if (ParseBoolFlag(argv[i], "benchmark_list_tests",
- &FLAGS_benchmark_list_tests) ||
- ParseStringFlag(argv[i], "benchmark_filter", &FLAGS_benchmark_filter) ||
- ParseDoubleFlag(argv[i], "benchmark_min_time",
- &FLAGS_benchmark_min_time) ||
- ParseInt32Flag(argv[i], "benchmark_repetitions",
- &FLAGS_benchmark_repetitions) ||
- ParseBoolFlag(argv[i], "benchmark_report_aggregates_only",
- &FLAGS_benchmark_report_aggregates_only) ||
- ParseBoolFlag(argv[i], "benchmark_display_aggregates_only",
- &FLAGS_benchmark_display_aggregates_only) ||
- ParseStringFlag(argv[i], "benchmark_format", &FLAGS_benchmark_format) ||
- ParseStringFlag(argv[i], "benchmark_out", &FLAGS_benchmark_out) ||
- ParseStringFlag(argv[i], "benchmark_out_format",
- &FLAGS_benchmark_out_format) ||
- ParseStringFlag(argv[i], "benchmark_color", &FLAGS_benchmark_color) ||
- // "color_print" is the deprecated name for "benchmark_color".
- // TODO: Remove this.
- ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) ||
- ParseBoolFlag(argv[i], "benchmark_counters_tabular",
- &FLAGS_benchmark_counters_tabular) ||
- ParseInt32Flag(argv[i], "v", &FLAGS_v)) {
- for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1];
-
- --(*argc);
- --i;
- } else if (IsFlag(argv[i], "help")) {
- PrintUsageAndExit();
- }
- }
- for (auto const* flag :
- {&FLAGS_benchmark_format, &FLAGS_benchmark_out_format})
- if (*flag != "console" && *flag != "json" && *flag != "csv") {
- PrintUsageAndExit();
- }
- if (FLAGS_benchmark_color.empty()) {
- PrintUsageAndExit();
- }
-}
-
-int InitializeStreams() {
- static std::ios_base::Init init;
- return 0;
-}
-
-} // end namespace internal
-
-void Initialize(int* argc, char** argv) {
- internal::ParseCommandLineFlags(argc, argv);
- internal::LogLevel() = FLAGS_v;
-}
-
-bool ReportUnrecognizedArguments(int argc, char** argv) {
- for (int i = 1; i < argc; ++i) {
- fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0],
- argv[i]);
- }
- return argc > 1;
-}
-
-} // end namespace benchmark
+++ /dev/null
-#include "benchmark_api_internal.h"
-
-namespace benchmark {
-namespace internal {
-
-State BenchmarkInstance::Run(IterationCount iters, int thread_id,
- internal::ThreadTimer* timer,
- internal::ThreadManager* manager) const {
- State st(iters, arg, thread_id, threads, timer, manager);
- benchmark->Run(st);
- return st;
-}
-
-} // internal
-} // benchmark
+++ /dev/null
-#ifndef BENCHMARK_API_INTERNAL_H
-#define BENCHMARK_API_INTERNAL_H
-
-#include "benchmark/benchmark.h"
-#include "commandlineflags.h"
-
-#include <cmath>
-#include <iosfwd>
-#include <limits>
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace benchmark {
-namespace internal {
-
-// Information kept per benchmark we may want to run
-struct BenchmarkInstance {
- BenchmarkName name;
- Benchmark* benchmark;
- AggregationReportMode aggregation_report_mode;
- std::vector<int64_t> arg;
- TimeUnit time_unit;
- int range_multiplier;
- bool measure_process_cpu_time;
- bool use_real_time;
- bool use_manual_time;
- BigO complexity;
- BigOFunc* complexity_lambda;
- UserCounters counters;
- const std::vector<Statistics>* statistics;
- bool last_benchmark_instance;
- int repetitions;
- double min_time;
- IterationCount iterations;
- int threads; // Number of concurrent threads to us
-
- State Run(IterationCount iters, int thread_id, internal::ThreadTimer* timer,
- internal::ThreadManager* manager) const;
-};
-
-bool FindBenchmarksInternal(const std::string& re,
- std::vector<BenchmarkInstance>* benchmarks,
- std::ostream* Err);
-
-bool IsZero(double n);
-
-ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color = false);
-
-} // end namespace internal
-} // end namespace benchmark
-
-#endif // BENCHMARK_API_INTERNAL_H
+++ /dev/null
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-
-BENCHMARK_MAIN();
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <benchmark/benchmark.h>
-
-namespace benchmark {
-
-namespace {
-
-// Compute the total size of a pack of std::strings
-size_t size_impl() { return 0; }
-
-template <typename Head, typename... Tail>
-size_t size_impl(const Head& head, const Tail&... tail) {
- return head.size() + size_impl(tail...);
-}
-
-// Join a pack of std::strings using a delimiter
-// TODO: use absl::StrJoin
-void join_impl(std::string&, char) {}
-
-template <typename Head, typename... Tail>
-void join_impl(std::string& s, const char delimiter, const Head& head,
- const Tail&... tail) {
- if (!s.empty() && !head.empty()) {
- s += delimiter;
- }
-
- s += head;
-
- join_impl(s, delimiter, tail...);
-}
-
-template <typename... Ts>
-std::string join(char delimiter, const Ts&... ts) {
- std::string s;
- s.reserve(sizeof...(Ts) + size_impl(ts...));
- join_impl(s, delimiter, ts...);
- return s;
-}
-} // namespace
-
-std::string BenchmarkName::str() const {
- return join('/', function_name, args, min_time, iterations, repetitions,
- time_type, threads);
-}
-} // namespace benchmark
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark_register.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#ifndef BENCHMARK_OS_FUCHSIA
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-
-#include <algorithm>
-#include <atomic>
-#include <condition_variable>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <sstream>
-#include <thread>
-
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS
-#endif
-#include <inttypes.h>
-
-#include "benchmark/benchmark.h"
-#include "benchmark_api_internal.h"
-#include "check.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "mutex.h"
-#include "re.h"
-#include "statistics.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-
-namespace {
-// For non-dense Range, intermediate values are powers of kRangeMultiplier.
-static const int kRangeMultiplier = 8;
-// The size of a benchmark family determines is the number of inputs to repeat
-// the benchmark on. If this is "large" then warn the user during configuration.
-static const size_t kMaxFamilySize = 100;
-} // end namespace
-
-namespace internal {
-
-//=============================================================================//
-// BenchmarkFamilies
-//=============================================================================//
-
-// Class for managing registered benchmarks. Note that each registered
-// benchmark identifies a family of related benchmarks to run.
-class BenchmarkFamilies {
- public:
- static BenchmarkFamilies* GetInstance();
-
- // Registers a benchmark family and returns the index assigned to it.
- size_t AddBenchmark(std::unique_ptr<Benchmark> family);
-
- // Clear all registered benchmark families.
- void ClearBenchmarks();
-
- // Extract the list of benchmark instances that match the specified
- // regular expression.
- bool FindBenchmarks(std::string re,
- std::vector<BenchmarkInstance>* benchmarks,
- std::ostream* Err);
-
- private:
- BenchmarkFamilies() {}
-
- std::vector<std::unique_ptr<Benchmark>> families_;
- Mutex mutex_;
-};
-
-BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
- static BenchmarkFamilies instance;
- return &instance;
-}
-
-size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr<Benchmark> family) {
- MutexLock l(mutex_);
- size_t index = families_.size();
- families_.push_back(std::move(family));
- return index;
-}
-
-void BenchmarkFamilies::ClearBenchmarks() {
- MutexLock l(mutex_);
- families_.clear();
- families_.shrink_to_fit();
-}
-
-bool BenchmarkFamilies::FindBenchmarks(
- std::string spec, std::vector<BenchmarkInstance>* benchmarks,
- std::ostream* ErrStream) {
- CHECK(ErrStream);
- auto& Err = *ErrStream;
- // Make regular expression out of command-line flag
- std::string error_msg;
- Regex re;
- bool isNegativeFilter = false;
- if (spec[0] == '-') {
- spec.replace(0, 1, "");
- isNegativeFilter = true;
- }
- if (!re.Init(spec, &error_msg)) {
- Err << "Could not compile benchmark re: " << error_msg << std::endl;
- return false;
- }
-
- // Special list of thread counts to use when none are specified
- const std::vector<int> one_thread = {1};
-
- MutexLock l(mutex_);
- for (std::unique_ptr<Benchmark>& family : families_) {
- // Family was deleted or benchmark doesn't match
- if (!family) continue;
-
- if (family->ArgsCnt() == -1) {
- family->Args({});
- }
- const std::vector<int>* thread_counts =
- (family->thread_counts_.empty()
- ? &one_thread
- : &static_cast<const std::vector<int>&>(family->thread_counts_));
- const size_t family_size = family->args_.size() * thread_counts->size();
- // The benchmark will be run at least 'family_size' different inputs.
- // If 'family_size' is very large warn the user.
- if (family_size > kMaxFamilySize) {
- Err << "The number of inputs is very large. " << family->name_
- << " will be repeated at least " << family_size << " times.\n";
- }
- // reserve in the special case the regex ".", since we know the final
- // family size.
- if (spec == ".") benchmarks->reserve(family_size);
-
- for (auto const& args : family->args_) {
- for (int num_threads : *thread_counts) {
- BenchmarkInstance instance;
- instance.name.function_name = family->name_;
- instance.benchmark = family.get();
- instance.aggregation_report_mode = family->aggregation_report_mode_;
- instance.arg = args;
- instance.time_unit = family->time_unit_;
- instance.range_multiplier = family->range_multiplier_;
- instance.min_time = family->min_time_;
- instance.iterations = family->iterations_;
- instance.repetitions = family->repetitions_;
- instance.measure_process_cpu_time = family->measure_process_cpu_time_;
- instance.use_real_time = family->use_real_time_;
- instance.use_manual_time = family->use_manual_time_;
- instance.complexity = family->complexity_;
- instance.complexity_lambda = family->complexity_lambda_;
- instance.statistics = &family->statistics_;
- instance.threads = num_threads;
-
- // Add arguments to instance name
- size_t arg_i = 0;
- for (auto const& arg : args) {
- if (!instance.name.args.empty()) {
- instance.name.args += '/';
- }
-
- if (arg_i < family->arg_names_.size()) {
- const auto& arg_name = family->arg_names_[arg_i];
- if (!arg_name.empty()) {
- instance.name.args += StrFormat("%s:", arg_name.c_str());
- }
- }
-
- instance.name.args += StrFormat("%" PRId64, arg);
- ++arg_i;
- }
-
- if (!IsZero(family->min_time_))
- instance.name.min_time =
- StrFormat("min_time:%0.3f", family->min_time_);
- if (family->iterations_ != 0) {
- instance.name.iterations =
- StrFormat("iterations:%lu",
- static_cast<unsigned long>(family->iterations_));
- }
- if (family->repetitions_ != 0)
- instance.name.repetitions =
- StrFormat("repeats:%d", family->repetitions_);
-
- if (family->measure_process_cpu_time_) {
- instance.name.time_type = "process_time";
- }
-
- if (family->use_manual_time_) {
- if (!instance.name.time_type.empty()) {
- instance.name.time_type += '/';
- }
- instance.name.time_type += "manual_time";
- } else if (family->use_real_time_) {
- if (!instance.name.time_type.empty()) {
- instance.name.time_type += '/';
- }
- instance.name.time_type += "real_time";
- }
-
- // Add the number of threads used to the name
- if (!family->thread_counts_.empty()) {
- instance.name.threads = StrFormat("threads:%d", instance.threads);
- }
-
- const auto full_name = instance.name.str();
- if ((re.Match(full_name) && !isNegativeFilter) ||
- (!re.Match(full_name) && isNegativeFilter)) {
- instance.last_benchmark_instance = (&args == &family->args_.back());
- benchmarks->push_back(std::move(instance));
- }
- }
- }
- }
- return true;
-}
-
-Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
- std::unique_ptr<Benchmark> bench_ptr(bench);
- BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
- families->AddBenchmark(std::move(bench_ptr));
- return bench;
-}
-
-// FIXME: This function is a hack so that benchmark.cc can access
-// `BenchmarkFamilies`
-bool FindBenchmarksInternal(const std::string& re,
- std::vector<BenchmarkInstance>* benchmarks,
- std::ostream* Err) {
- return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
-}
-
-//=============================================================================//
-// Benchmark
-//=============================================================================//
-
-Benchmark::Benchmark(const char* name)
- : name_(name),
- aggregation_report_mode_(ARM_Unspecified),
- time_unit_(kNanosecond),
- range_multiplier_(kRangeMultiplier),
- min_time_(0),
- iterations_(0),
- repetitions_(0),
- measure_process_cpu_time_(false),
- use_real_time_(false),
- use_manual_time_(false),
- complexity_(oNone),
- complexity_lambda_(nullptr) {
- ComputeStatistics("mean", StatisticsMean);
- ComputeStatistics("median", StatisticsMedian);
- ComputeStatistics("stddev", StatisticsStdDev);
-}
-
-Benchmark::~Benchmark() {}
-
-Benchmark* Benchmark::Arg(int64_t x) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
- args_.push_back({x});
- return this;
-}
-
-Benchmark* Benchmark::Unit(TimeUnit unit) {
- time_unit_ = unit;
- return this;
-}
-
-Benchmark* Benchmark::Range(int64_t start, int64_t limit) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
- std::vector<int64_t> arglist;
- AddRange(&arglist, start, limit, range_multiplier_);
-
- for (int64_t i : arglist) {
- args_.push_back({i});
- }
- return this;
-}
-
-Benchmark* Benchmark::Ranges(
- const std::vector<std::pair<int64_t, int64_t>>& ranges) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
- std::vector<std::vector<int64_t>> arglists(ranges.size());
- std::size_t total = 1;
- for (std::size_t i = 0; i < ranges.size(); i++) {
- AddRange(&arglists[i], ranges[i].first, ranges[i].second,
- range_multiplier_);
- total *= arglists[i].size();
- }
-
- std::vector<std::size_t> ctr(arglists.size(), 0);
-
- for (std::size_t i = 0; i < total; i++) {
- std::vector<int64_t> tmp;
- tmp.reserve(arglists.size());
-
- for (std::size_t j = 0; j < arglists.size(); j++) {
- tmp.push_back(arglists[j].at(ctr[j]));
- }
-
- args_.push_back(std::move(tmp));
-
- for (std::size_t j = 0; j < arglists.size(); j++) {
- if (ctr[j] + 1 < arglists[j].size()) {
- ++ctr[j];
- break;
- }
- ctr[j] = 0;
- }
- }
- return this;
-}
-
-Benchmark* Benchmark::ArgName(const std::string& name) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
- arg_names_ = {name};
- return this;
-}
-
-Benchmark* Benchmark::ArgNames(const std::vector<std::string>& names) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(names.size()));
- arg_names_ = names;
- return this;
-}
-
-Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
- CHECK_LE(start, limit);
- for (int64_t arg = start; arg <= limit; arg += step) {
- args_.push_back({arg});
- }
- return this;
-}
-
-Benchmark* Benchmark::Args(const std::vector<int64_t>& args) {
- CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(args.size()));
- args_.push_back(args);
- return this;
-}
-
-Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
- custom_arguments(this);
- return this;
-}
-
-Benchmark* Benchmark::RangeMultiplier(int multiplier) {
- CHECK(multiplier > 1);
- range_multiplier_ = multiplier;
- return this;
-}
-
-Benchmark* Benchmark::MinTime(double t) {
- CHECK(t > 0.0);
- CHECK(iterations_ == 0);
- min_time_ = t;
- return this;
-}
-
-Benchmark* Benchmark::Iterations(IterationCount n) {
- CHECK(n > 0);
- CHECK(IsZero(min_time_));
- iterations_ = n;
- return this;
-}
-
-Benchmark* Benchmark::Repetitions(int n) {
- CHECK(n > 0);
- repetitions_ = n;
- return this;
-}
-
-Benchmark* Benchmark::ReportAggregatesOnly(bool value) {
- aggregation_report_mode_ = value ? ARM_ReportAggregatesOnly : ARM_Default;
- return this;
-}
-
-Benchmark* Benchmark::DisplayAggregatesOnly(bool value) {
- // If we were called, the report mode is no longer 'unspecified', in any case.
- aggregation_report_mode_ = static_cast<AggregationReportMode>(
- aggregation_report_mode_ | ARM_Default);
-
- if (value) {
- aggregation_report_mode_ = static_cast<AggregationReportMode>(
- aggregation_report_mode_ | ARM_DisplayReportAggregatesOnly);
- } else {
- aggregation_report_mode_ = static_cast<AggregationReportMode>(
- aggregation_report_mode_ & ~ARM_DisplayReportAggregatesOnly);
- }
-
- return this;
-}
-
-Benchmark* Benchmark::MeasureProcessCPUTime() {
- // Can be used together with UseRealTime() / UseManualTime().
- measure_process_cpu_time_ = true;
- return this;
-}
-
-Benchmark* Benchmark::UseRealTime() {
- CHECK(!use_manual_time_)
- << "Cannot set UseRealTime and UseManualTime simultaneously.";
- use_real_time_ = true;
- return this;
-}
-
-Benchmark* Benchmark::UseManualTime() {
- CHECK(!use_real_time_)
- << "Cannot set UseRealTime and UseManualTime simultaneously.";
- use_manual_time_ = true;
- return this;
-}
-
-Benchmark* Benchmark::Complexity(BigO complexity) {
- complexity_ = complexity;
- return this;
-}
-
-Benchmark* Benchmark::Complexity(BigOFunc* complexity) {
- complexity_lambda_ = complexity;
- complexity_ = oLambda;
- return this;
-}
-
-Benchmark* Benchmark::ComputeStatistics(std::string name,
- StatisticsFunc* statistics) {
- statistics_.emplace_back(name, statistics);
- return this;
-}
-
-Benchmark* Benchmark::Threads(int t) {
- CHECK_GT(t, 0);
- thread_counts_.push_back(t);
- return this;
-}
-
-Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
- CHECK_GT(min_threads, 0);
- CHECK_GE(max_threads, min_threads);
-
- AddRange(&thread_counts_, min_threads, max_threads, 2);
- return this;
-}
-
-Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads,
- int stride) {
- CHECK_GT(min_threads, 0);
- CHECK_GE(max_threads, min_threads);
- CHECK_GE(stride, 1);
-
- for (auto i = min_threads; i < max_threads; i += stride) {
- thread_counts_.push_back(i);
- }
- thread_counts_.push_back(max_threads);
- return this;
-}
-
-Benchmark* Benchmark::ThreadPerCpu() {
- thread_counts_.push_back(CPUInfo::Get().num_cpus);
- return this;
-}
-
-void Benchmark::SetName(const char* name) { name_ = name; }
-
-int Benchmark::ArgsCnt() const {
- if (args_.empty()) {
- if (arg_names_.empty()) return -1;
- return static_cast<int>(arg_names_.size());
- }
- return static_cast<int>(args_.front().size());
-}
-
-//=============================================================================//
-// FunctionBenchmark
-//=============================================================================//
-
-void FunctionBenchmark::Run(State& st) { func_(st); }
-
-} // end namespace internal
-
-void ClearRegisteredBenchmarks() {
- internal::BenchmarkFamilies::GetInstance()->ClearBenchmarks();
-}
-
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_REGISTER_H
-#define BENCHMARK_REGISTER_H
-
-#include <vector>
-
-#include "check.h"
-
-namespace benchmark {
-namespace internal {
-
-// Append the powers of 'mult' in the closed interval [lo, hi].
-// Returns iterator to the start of the inserted range.
-template <typename T>
-typename std::vector<T>::iterator
-AddPowers(std::vector<T>* dst, T lo, T hi, int mult) {
- CHECK_GE(lo, 0);
- CHECK_GE(hi, lo);
- CHECK_GE(mult, 2);
-
- const size_t start_offset = dst->size();
-
- static const T kmax = std::numeric_limits<T>::max();
-
- // Space out the values in multiples of "mult"
- for (T i = 1; i <= hi; i *= mult) {
- if (i >= lo) {
- dst->push_back(i);
- }
- // Break the loop here since multiplying by
- // 'mult' would move outside of the range of T
- if (i > kmax / mult) break;
- }
-
- return dst->begin() + start_offset;
-}
-
-template <typename T>
-void AddNegatedPowers(std::vector<T>* dst, T lo, T hi, int mult) {
- // We negate lo and hi so we require that they cannot be equal to 'min'.
- CHECK_GT(lo, std::numeric_limits<T>::min());
- CHECK_GT(hi, std::numeric_limits<T>::min());
- CHECK_GE(hi, lo);
- CHECK_LE(hi, 0);
-
- // Add positive powers, then negate and reverse.
- // Casts necessary since small integers get promoted
- // to 'int' when negating.
- const auto lo_complement = static_cast<T>(-lo);
- const auto hi_complement = static_cast<T>(-hi);
-
- const auto it = AddPowers(dst, hi_complement, lo_complement, mult);
-
- std::for_each(it, dst->end(), [](T& t) { t *= -1; });
- std::reverse(it, dst->end());
-}
-
-template <typename T>
-void AddRange(std::vector<T>* dst, T lo, T hi, int mult) {
- static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
- "Args type must be a signed integer");
-
- CHECK_GE(hi, lo);
- CHECK_GE(mult, 2);
-
- // Add "lo"
- dst->push_back(lo);
-
- // Handle lo == hi as a special case, so we then know
- // lo < hi and so it is safe to add 1 to lo and subtract 1
- // from hi without falling outside of the range of T.
- if (lo == hi) return;
-
- // Ensure that lo_inner <= hi_inner below.
- if (lo + 1 == hi) {
- dst->push_back(hi);
- return;
- }
-
- // Add all powers of 'mult' in the range [lo+1, hi-1] (inclusive).
- const auto lo_inner = static_cast<T>(lo + 1);
- const auto hi_inner = static_cast<T>(hi - 1);
-
- // Insert negative values
- if (lo_inner < 0) {
- AddNegatedPowers(dst, lo_inner, std::min(hi_inner, T{-1}), mult);
- }
-
- // Treat 0 as a special case (see discussion on #762).
- if (lo <= 0 && hi >= 0) {
- dst->push_back(0);
- }
-
- // Insert positive values
- if (hi_inner > 0) {
- AddPowers(dst, std::max(lo_inner, T{1}), hi_inner, mult);
- }
-
- // Add "hi" (if different from last value).
- if (hi != dst->back()) {
- dst->push_back(hi);
- }
-}
-
-} // namespace internal
-} // namespace benchmark
-
-#endif // BENCHMARK_REGISTER_H
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark_runner.h"
-#include "benchmark/benchmark.h"
-#include "benchmark_api_internal.h"
-#include "internal_macros.h"
-
-#ifndef BENCHMARK_OS_WINDOWS
-#ifndef BENCHMARK_OS_FUCHSIA
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#include <unistd.h>
-#endif
-
-#include <algorithm>
-#include <atomic>
-#include <condition_variable>
-#include <cstdio>
-#include <cstdlib>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <string>
-#include <thread>
-#include <utility>
-
-#include "check.h"
-#include "colorprint.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "counter.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "mutex.h"
-#include "re.h"
-#include "statistics.h"
-#include "string_util.h"
-#include "thread_manager.h"
-#include "thread_timer.h"
-
-namespace benchmark {
-
-namespace internal {
-
-MemoryManager* memory_manager = nullptr;
-
-namespace {
-
-static constexpr IterationCount kMaxIterations = 1000000000;
-
-BenchmarkReporter::Run CreateRunReport(
- const benchmark::internal::BenchmarkInstance& b,
- const internal::ThreadManager::Result& results,
- IterationCount memory_iterations,
- const MemoryManager::Result& memory_result, double seconds,
- int64_t repetition_index) {
- // Create report about this benchmark run.
- BenchmarkReporter::Run report;
-
- report.run_name = b.name;
- report.error_occurred = results.has_error_;
- report.error_message = results.error_message_;
- report.report_label = results.report_label_;
- // This is the total iterations across all threads.
- report.iterations = results.iterations;
- report.time_unit = b.time_unit;
- report.threads = b.threads;
- report.repetition_index = repetition_index;
- report.repetitions = b.repetitions;
-
- if (!report.error_occurred) {
- if (b.use_manual_time) {
- report.real_accumulated_time = results.manual_time_used;
- } else {
- report.real_accumulated_time = results.real_time_used;
- }
- report.cpu_accumulated_time = results.cpu_time_used;
- report.complexity_n = results.complexity_n;
- report.complexity = b.complexity;
- report.complexity_lambda = b.complexity_lambda;
- report.statistics = b.statistics;
- report.counters = results.counters;
-
- if (memory_iterations > 0) {
- report.has_memory_result = true;
- report.allocs_per_iter =
- memory_iterations ? static_cast<double>(memory_result.num_allocs) /
- memory_iterations
- : 0;
- report.max_bytes_used = memory_result.max_bytes_used;
- }
-
- internal::Finish(&report.counters, results.iterations, seconds, b.threads);
- }
- return report;
-}
-
-// Execute one thread of benchmark b for the specified number of iterations.
-// Adds the stats collected for the thread into *total.
-void RunInThread(const BenchmarkInstance* b, IterationCount iters,
- int thread_id, ThreadManager* manager) {
- internal::ThreadTimer timer(
- b->measure_process_cpu_time
- ? internal::ThreadTimer::CreateProcessCpuTime()
- : internal::ThreadTimer::Create());
- State st = b->Run(iters, thread_id, &timer, manager);
- CHECK(st.error_occurred() || st.iterations() >= st.max_iterations)
- << "Benchmark returned before State::KeepRunning() returned false!";
- {
- MutexLock l(manager->GetBenchmarkMutex());
- internal::ThreadManager::Result& results = manager->results;
- results.iterations += st.iterations();
- results.cpu_time_used += timer.cpu_time_used();
- results.real_time_used += timer.real_time_used();
- results.manual_time_used += timer.manual_time_used();
- results.complexity_n += st.complexity_length_n();
- internal::Increment(&results.counters, st.counters);
- }
- manager->NotifyThreadComplete();
-}
-
-class BenchmarkRunner {
- public:
- BenchmarkRunner(const benchmark::internal::BenchmarkInstance& b_,
- std::vector<BenchmarkReporter::Run>* complexity_reports_)
- : b(b_),
- complexity_reports(*complexity_reports_),
- min_time(!IsZero(b.min_time) ? b.min_time : FLAGS_benchmark_min_time),
- repeats(b.repetitions != 0 ? b.repetitions
- : FLAGS_benchmark_repetitions),
- has_explicit_iteration_count(b.iterations != 0),
- pool(b.threads - 1),
- iters(has_explicit_iteration_count ? b.iterations : 1) {
- run_results.display_report_aggregates_only =
- (FLAGS_benchmark_report_aggregates_only ||
- FLAGS_benchmark_display_aggregates_only);
- run_results.file_report_aggregates_only =
- FLAGS_benchmark_report_aggregates_only;
- if (b.aggregation_report_mode != internal::ARM_Unspecified) {
- run_results.display_report_aggregates_only =
- (b.aggregation_report_mode &
- internal::ARM_DisplayReportAggregatesOnly);
- run_results.file_report_aggregates_only =
- (b.aggregation_report_mode & internal::ARM_FileReportAggregatesOnly);
- }
-
- for (int repetition_num = 0; repetition_num < repeats; repetition_num++) {
- DoOneRepetition(repetition_num);
- }
-
- // Calculate additional statistics
- run_results.aggregates_only = ComputeStats(run_results.non_aggregates);
-
- // Maybe calculate complexity report
- if ((b.complexity != oNone) && b.last_benchmark_instance) {
- auto additional_run_stats = ComputeBigO(complexity_reports);
- run_results.aggregates_only.insert(run_results.aggregates_only.end(),
- additional_run_stats.begin(),
- additional_run_stats.end());
- complexity_reports.clear();
- }
- }
-
- RunResults&& get_results() { return std::move(run_results); }
-
- private:
- RunResults run_results;
-
- const benchmark::internal::BenchmarkInstance& b;
- std::vector<BenchmarkReporter::Run>& complexity_reports;
-
- const double min_time;
- const int repeats;
- const bool has_explicit_iteration_count;
-
- std::vector<std::thread> pool;
-
- IterationCount iters; // preserved between repetitions!
- // So only the first repetition has to find/calculate it,
- // the other repetitions will just use that precomputed iteration count.
-
- struct IterationResults {
- internal::ThreadManager::Result results;
- IterationCount iters;
- double seconds;
- };
- IterationResults DoNIterations() {
- VLOG(2) << "Running " << b.name.str() << " for " << iters << "\n";
-
- std::unique_ptr<internal::ThreadManager> manager;
- manager.reset(new internal::ThreadManager(b.threads));
-
- // Run all but one thread in separate threads
- for (std::size_t ti = 0; ti < pool.size(); ++ti) {
- pool[ti] = std::thread(&RunInThread, &b, iters, static_cast<int>(ti + 1),
- manager.get());
- }
- // And run one thread here directly.
- // (If we were asked to run just one thread, we don't create new threads.)
- // Yes, we need to do this here *after* we start the separate threads.
- RunInThread(&b, iters, 0, manager.get());
-
- // The main thread has finished. Now let's wait for the other threads.
- manager->WaitForAllThreads();
- for (std::thread& thread : pool) thread.join();
-
- IterationResults i;
- // Acquire the measurements/counters from the manager, UNDER THE LOCK!
- {
- MutexLock l(manager->GetBenchmarkMutex());
- i.results = manager->results;
- }
-
- // And get rid of the manager.
- manager.reset();
-
- // Adjust real/manual time stats since they were reported per thread.
- i.results.real_time_used /= b.threads;
- i.results.manual_time_used /= b.threads;
- // If we were measuring whole-process CPU usage, adjust the CPU time too.
- if (b.measure_process_cpu_time) i.results.cpu_time_used /= b.threads;
-
- VLOG(2) << "Ran in " << i.results.cpu_time_used << "/"
- << i.results.real_time_used << "\n";
-
- // So for how long were we running?
- i.iters = iters;
- // Base decisions off of real time if requested by this benchmark.
- i.seconds = i.results.cpu_time_used;
- if (b.use_manual_time) {
- i.seconds = i.results.manual_time_used;
- } else if (b.use_real_time) {
- i.seconds = i.results.real_time_used;
- }
-
- return i;
- }
-
- IterationCount PredictNumItersNeeded(const IterationResults& i) const {
- // See how much iterations should be increased by.
- // Note: Avoid division by zero with max(seconds, 1ns).
- double multiplier = min_time * 1.4 / std::max(i.seconds, 1e-9);
- // If our last run was at least 10% of FLAGS_benchmark_min_time then we
- // use the multiplier directly.
- // Otherwise we use at most 10 times expansion.
- // NOTE: When the last run was at least 10% of the min time the max
- // expansion should be 14x.
- bool is_significant = (i.seconds / min_time) > 0.1;
- multiplier = is_significant ? multiplier : std::min(10.0, multiplier);
- if (multiplier <= 1.0) multiplier = 2.0;
-
- // So what seems to be the sufficiently-large iteration count? Round up.
- const IterationCount max_next_iters = static_cast<IterationCount>(
- std::lround(std::max(multiplier * static_cast<double>(i.iters),
- static_cast<double>(i.iters) + 1.0)));
- // But we do have *some* sanity limits though..
- const IterationCount next_iters = std::min(max_next_iters, kMaxIterations);
-
- VLOG(3) << "Next iters: " << next_iters << ", " << multiplier << "\n";
- return next_iters; // round up before conversion to integer.
- }
-
- bool ShouldReportIterationResults(const IterationResults& i) const {
- // Determine if this run should be reported;
- // Either it has run for a sufficient amount of time
- // or because an error was reported.
- return i.results.has_error_ ||
- i.iters >= kMaxIterations || // Too many iterations already.
- i.seconds >= min_time || // The elapsed time is large enough.
- // CPU time is specified but the elapsed real time greatly exceeds
- // the minimum time.
- // Note that user provided timers are except from this sanity check.
- ((i.results.real_time_used >= 5 * min_time) && !b.use_manual_time);
- }
-
- void DoOneRepetition(int64_t repetition_index) {
- const bool is_the_first_repetition = repetition_index == 0;
- IterationResults i;
-
- // We *may* be gradually increasing the length (iteration count)
- // of the benchmark until we decide the results are significant.
- // And once we do, we report those last results and exit.
- // Please do note that the if there are repetitions, the iteration count
- // is *only* calculated for the *first* repetition, and other repetitions
- // simply use that precomputed iteration count.
- for (;;) {
- i = DoNIterations();
-
- // Do we consider the results to be significant?
- // If we are doing repetitions, and the first repetition was already done,
- // it has calculated the correct iteration time, so we have run that very
- // iteration count just now. No need to calculate anything. Just report.
- // Else, the normal rules apply.
- const bool results_are_significant = !is_the_first_repetition ||
- has_explicit_iteration_count ||
- ShouldReportIterationResults(i);
-
- if (results_are_significant) break; // Good, let's report them!
-
- // Nope, bad iteration. Let's re-estimate the hopefully-sufficient
- // iteration count, and run the benchmark again...
-
- iters = PredictNumItersNeeded(i);
- assert(iters > i.iters &&
- "if we did more iterations than we want to do the next time, "
- "then we should have accepted the current iteration run.");
- }
-
- // Oh, one last thing, we need to also produce the 'memory measurements'..
- MemoryManager::Result memory_result;
- IterationCount memory_iterations = 0;
- if (memory_manager != nullptr) {
- // Only run a few iterations to reduce the impact of one-time
- // allocations in benchmarks that are not properly managed.
- memory_iterations = std::min<IterationCount>(16, iters);
- memory_manager->Start();
- std::unique_ptr<internal::ThreadManager> manager;
- manager.reset(new internal::ThreadManager(1));
- RunInThread(&b, memory_iterations, 0, manager.get());
- manager->WaitForAllThreads();
- manager.reset();
-
- memory_manager->Stop(&memory_result);
- }
-
- // Ok, now actualy report.
- BenchmarkReporter::Run report =
- CreateRunReport(b, i.results, memory_iterations, memory_result,
- i.seconds, repetition_index);
-
- if (!report.error_occurred && b.complexity != oNone)
- complexity_reports.push_back(report);
-
- run_results.non_aggregates.push_back(report);
- }
-};
-
-} // end namespace
-
-RunResults RunBenchmark(
- const benchmark::internal::BenchmarkInstance& b,
- std::vector<BenchmarkReporter::Run>* complexity_reports) {
- internal::BenchmarkRunner r(b, complexity_reports);
- return r.get_results();
-}
-
-} // end namespace internal
-
-} // end namespace benchmark
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_RUNNER_H_
-#define BENCHMARK_RUNNER_H_
-
-#include "benchmark_api_internal.h"
-#include "internal_macros.h"
-
-DECLARE_double(benchmark_min_time);
-
-DECLARE_int32(benchmark_repetitions);
-
-DECLARE_bool(benchmark_report_aggregates_only);
-
-DECLARE_bool(benchmark_display_aggregates_only);
-
-namespace benchmark {
-
-namespace internal {
-
-extern MemoryManager* memory_manager;
-
-struct RunResults {
- std::vector<BenchmarkReporter::Run> non_aggregates;
- std::vector<BenchmarkReporter::Run> aggregates_only;
-
- bool display_report_aggregates_only = false;
- bool file_report_aggregates_only = false;
-};
-
-RunResults RunBenchmark(
- const benchmark::internal::BenchmarkInstance& b,
- std::vector<BenchmarkReporter::Run>* complexity_reports);
-
-} // namespace internal
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_RUNNER_H_
+++ /dev/null
-#ifndef CHECK_H_
-#define CHECK_H_
-
-#include <cmath>
-#include <cstdlib>
-#include <ostream>
-
-#include "internal_macros.h"
-#include "log.h"
-
-namespace benchmark {
-namespace internal {
-
-typedef void(AbortHandlerT)();
-
-inline AbortHandlerT*& GetAbortHandler() {
- static AbortHandlerT* handler = &std::abort;
- return handler;
-}
-
-BENCHMARK_NORETURN inline void CallAbortHandler() {
- GetAbortHandler()();
- std::abort(); // fallback to enforce noreturn
-}
-
-// CheckHandler is the class constructed by failing CHECK macros. CheckHandler
-// will log information about the failures and abort when it is destructed.
-class CheckHandler {
- public:
- CheckHandler(const char* check, const char* file, const char* func, int line)
- : log_(GetErrorLogInstance()) {
- log_ << file << ":" << line << ": " << func << ": Check `" << check
- << "' failed. ";
- }
-
- LogType& GetLog() { return log_; }
-
- BENCHMARK_NORETURN ~CheckHandler() BENCHMARK_NOEXCEPT_OP(false) {
- log_ << std::endl;
- CallAbortHandler();
- }
-
- CheckHandler& operator=(const CheckHandler&) = delete;
- CheckHandler(const CheckHandler&) = delete;
- CheckHandler() = delete;
-
- private:
- LogType& log_;
-};
-
-} // end namespace internal
-} // end namespace benchmark
-
-// The CHECK macro returns a std::ostream object that can have extra information
-// written to it.
-#ifndef NDEBUG
-#define CHECK(b) \
- (b ? ::benchmark::internal::GetNullLogInstance() \
- : ::benchmark::internal::CheckHandler(#b, __FILE__, __func__, __LINE__) \
- .GetLog())
-#else
-#define CHECK(b) ::benchmark::internal::GetNullLogInstance()
-#endif
-
-// clang-format off
-// preserve whitespacing between operators for alignment
-#define CHECK_EQ(a, b) CHECK((a) == (b))
-#define CHECK_NE(a, b) CHECK((a) != (b))
-#define CHECK_GE(a, b) CHECK((a) >= (b))
-#define CHECK_LE(a, b) CHECK((a) <= (b))
-#define CHECK_GT(a, b) CHECK((a) > (b))
-#define CHECK_LT(a, b) CHECK((a) < (b))
-
-#define CHECK_FLOAT_EQ(a, b, eps) CHECK(std::fabs((a) - (b)) < (eps))
-#define CHECK_FLOAT_NE(a, b, eps) CHECK(std::fabs((a) - (b)) >= (eps))
-#define CHECK_FLOAT_GE(a, b, eps) CHECK((a) - (b) > -(eps))
-#define CHECK_FLOAT_LE(a, b, eps) CHECK((b) - (a) > -(eps))
-#define CHECK_FLOAT_GT(a, b, eps) CHECK((a) - (b) > (eps))
-#define CHECK_FLOAT_LT(a, b, eps) CHECK((b) - (a) > (eps))
-//clang-format on
-
-#endif // CHECK_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "colorprint.h"
-
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <memory>
-#include <string>
-
-#include "check.h"
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include <windows.h>
-#include <io.h>
-#else
-#include <unistd.h>
-#endif // BENCHMARK_OS_WINDOWS
-
-namespace benchmark {
-namespace {
-#ifdef BENCHMARK_OS_WINDOWS
-typedef WORD PlatformColorCode;
-#else
-typedef const char* PlatformColorCode;
-#endif
-
-PlatformColorCode GetPlatformColorCode(LogColor color) {
-#ifdef BENCHMARK_OS_WINDOWS
- switch (color) {
- case COLOR_RED:
- return FOREGROUND_RED;
- case COLOR_GREEN:
- return FOREGROUND_GREEN;
- case COLOR_YELLOW:
- return FOREGROUND_RED | FOREGROUND_GREEN;
- case COLOR_BLUE:
- return FOREGROUND_BLUE;
- case COLOR_MAGENTA:
- return FOREGROUND_BLUE | FOREGROUND_RED;
- case COLOR_CYAN:
- return FOREGROUND_BLUE | FOREGROUND_GREEN;
- case COLOR_WHITE: // fall through to default
- default:
- return 0;
- }
-#else
- switch (color) {
- case COLOR_RED:
- return "1";
- case COLOR_GREEN:
- return "2";
- case COLOR_YELLOW:
- return "3";
- case COLOR_BLUE:
- return "4";
- case COLOR_MAGENTA:
- return "5";
- case COLOR_CYAN:
- return "6";
- case COLOR_WHITE:
- return "7";
- default:
- return nullptr;
- };
-#endif
-}
-
-} // end namespace
-
-std::string FormatString(const char* msg, va_list args) {
- // we might need a second shot at this, so pre-emptivly make a copy
- va_list args_cp;
- va_copy(args_cp, args);
-
- std::size_t size = 256;
- char local_buff[256];
- auto ret = vsnprintf(local_buff, size, msg, args_cp);
-
- va_end(args_cp);
-
- // currently there is no error handling for failure, so this is hack.
- CHECK(ret >= 0);
-
- if (ret == 0) // handle empty expansion
- return {};
- else if (static_cast<size_t>(ret) < size)
- return local_buff;
- else {
- // we did not provide a long enough buffer on our first attempt.
- size = (size_t)ret + 1; // + 1 for the null byte
- std::unique_ptr<char[]> buff(new char[size]);
- ret = vsnprintf(buff.get(), size, msg, args);
- CHECK(ret > 0 && ((size_t)ret) < size);
- return buff.get();
- }
-}
-
-std::string FormatString(const char* msg, ...) {
- va_list args;
- va_start(args, msg);
- auto tmp = FormatString(msg, args);
- va_end(args);
- return tmp;
-}
-
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
- ColorPrintf(out, color, fmt, args);
- va_end(args);
-}
-
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,
- va_list args) {
-#ifdef BENCHMARK_OS_WINDOWS
- ((void)out); // suppress unused warning
-
- const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
-
- // Gets the current text color.
- CONSOLE_SCREEN_BUFFER_INFO buffer_info;
- GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
- const WORD old_color_attrs = buffer_info.wAttributes;
-
- // We need to flush the stream buffers into the console before each
- // SetConsoleTextAttribute call lest it affect the text that is already
- // printed but has not yet reached the console.
- fflush(stdout);
- SetConsoleTextAttribute(stdout_handle,
- GetPlatformColorCode(color) | FOREGROUND_INTENSITY);
- vprintf(fmt, args);
-
- fflush(stdout);
- // Restores the text color.
- SetConsoleTextAttribute(stdout_handle, old_color_attrs);
-#else
- const char* color_code = GetPlatformColorCode(color);
- if (color_code) out << FormatString("\033[0;3%sm", color_code);
- out << FormatString(fmt, args) << "\033[m";
-#endif
-}
-
-bool IsColorTerminal() {
-#if BENCHMARK_OS_WINDOWS
- // On Windows the TERM variable is usually not set, but the
- // console there does support colors.
- return 0 != _isatty(_fileno(stdout));
-#else
- // On non-Windows platforms, we rely on the TERM variable. This list of
- // supported TERM values is copied from Google Test:
- // <https://github.com/google/googletest/blob/master/googletest/src/gtest.cc#L2925>.
- const char* const SUPPORTED_TERM_VALUES[] = {
- "xterm", "xterm-color", "xterm-256color",
- "screen", "screen-256color", "tmux",
- "tmux-256color", "rxvt-unicode", "rxvt-unicode-256color",
- "linux", "cygwin",
- };
-
- const char* const term = getenv("TERM");
-
- bool term_supports_color = false;
- for (const char* candidate : SUPPORTED_TERM_VALUES) {
- if (term && 0 == strcmp(term, candidate)) {
- term_supports_color = true;
- break;
- }
- }
-
- return 0 != isatty(fileno(stdout)) && term_supports_color;
-#endif // BENCHMARK_OS_WINDOWS
-}
-
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_COLORPRINT_H_
-#define BENCHMARK_COLORPRINT_H_
-
-#include <cstdarg>
-#include <iostream>
-#include <string>
-
-namespace benchmark {
-enum LogColor {
- COLOR_DEFAULT,
- COLOR_RED,
- COLOR_GREEN,
- COLOR_YELLOW,
- COLOR_BLUE,
- COLOR_MAGENTA,
- COLOR_CYAN,
- COLOR_WHITE
-};
-
-std::string FormatString(const char* msg, va_list args);
-std::string FormatString(const char* msg, ...);
-
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt,
- va_list args);
-void ColorPrintf(std::ostream& out, LogColor color, const char* fmt, ...);
-
-// Returns true if stdout appears to be a terminal that supports colored
-// output, false otherwise.
-bool IsColorTerminal();
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_COLORPRINT_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "commandlineflags.h"
-
-#include <algorithm>
-#include <cctype>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <limits>
-
-namespace benchmark {
-namespace {
-
-// Parses 'str' for a 32-bit signed integer. If successful, writes
-// the result to *value and returns true; otherwise leaves *value
-// unchanged and returns false.
-bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) {
- // Parses the environment variable as a decimal integer.
- char* end = nullptr;
- const long long_value = strtol(str, &end, 10); // NOLINT
-
- // Has strtol() consumed all characters in the string?
- if (*end != '\0') {
- // No - an invalid character was encountered.
- std::cerr << src_text << " is expected to be a 32-bit integer, "
- << "but actually has value \"" << str << "\".\n";
- return false;
- }
-
- // Is the parsed value in the range of an Int32?
- const int32_t result = static_cast<int32_t>(long_value);
- if (long_value == std::numeric_limits<long>::max() ||
- long_value == std::numeric_limits<long>::min() ||
- // The parsed value overflows as a long. (strtol() returns
- // LONG_MAX or LONG_MIN when the input overflows.)
- result != long_value
- // The parsed value overflows as an Int32.
- ) {
- std::cerr << src_text << " is expected to be a 32-bit integer, "
- << "but actually has value \"" << str << "\", "
- << "which overflows.\n";
- return false;
- }
-
- *value = result;
- return true;
-}
-
-// Parses 'str' for a double. If successful, writes the result to *value and
-// returns true; otherwise leaves *value unchanged and returns false.
-bool ParseDouble(const std::string& src_text, const char* str, double* value) {
- // Parses the environment variable as a decimal integer.
- char* end = nullptr;
- const double double_value = strtod(str, &end); // NOLINT
-
- // Has strtol() consumed all characters in the string?
- if (*end != '\0') {
- // No - an invalid character was encountered.
- std::cerr << src_text << " is expected to be a double, "
- << "but actually has value \"" << str << "\".\n";
- return false;
- }
-
- *value = double_value;
- return true;
-}
-
-// Returns the name of the environment variable corresponding to the
-// given flag. For example, FlagToEnvVar("foo") will return
-// "BENCHMARK_FOO" in the open-source version.
-static std::string FlagToEnvVar(const char* flag) {
- const std::string flag_str(flag);
-
- std::string env_var;
- for (size_t i = 0; i != flag_str.length(); ++i)
- env_var += static_cast<char>(::toupper(flag_str.c_str()[i]));
-
- return "BENCHMARK_" + env_var;
-}
-
-} // namespace
-
-bool BoolFromEnv(const char* flag, bool default_val) {
- const std::string env_var = FlagToEnvVar(flag);
- const char* const value_str = getenv(env_var.c_str());
- return value_str == nullptr ? default_val : IsTruthyFlagValue(value_str);
-}
-
-int32_t Int32FromEnv(const char* flag, int32_t default_val) {
- const std::string env_var = FlagToEnvVar(flag);
- const char* const value_str = getenv(env_var.c_str());
- int32_t value = default_val;
- if (value_str == nullptr ||
- !ParseInt32(std::string("Environment variable ") + env_var, value_str,
- &value)) {
- return default_val;
- }
- return value;
-}
-
-double DoubleFromEnv(const char* flag, double default_val) {
- const std::string env_var = FlagToEnvVar(flag);
- const char* const value_str = getenv(env_var.c_str());
- double value = default_val;
- if (value_str == nullptr ||
- !ParseDouble(std::string("Environment variable ") + env_var, value_str,
- &value)) {
- return default_val;
- }
- return value;
-}
-
-const char* StringFromEnv(const char* flag, const char* default_val) {
- const std::string env_var = FlagToEnvVar(flag);
- const char* const value = getenv(env_var.c_str());
- return value == nullptr ? default_val : value;
-}
-
-// Parses a string as a command line flag. The string should have
-// the format "--flag=value". When def_optional is true, the "=value"
-// part can be omitted.
-//
-// Returns the value of the flag, or nullptr if the parsing failed.
-const char* ParseFlagValue(const char* str, const char* flag,
- bool def_optional) {
- // str and flag must not be nullptr.
- if (str == nullptr || flag == nullptr) return nullptr;
-
- // The flag must start with "--".
- const std::string flag_str = std::string("--") + std::string(flag);
- const size_t flag_len = flag_str.length();
- if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr;
-
- // Skips the flag name.
- const char* flag_end = str + flag_len;
-
- // When def_optional is true, it's OK to not have a "=value" part.
- if (def_optional && (flag_end[0] == '\0')) return flag_end;
-
- // If def_optional is true and there are more characters after the
- // flag name, or if def_optional is false, there must be a '=' after
- // the flag name.
- if (flag_end[0] != '=') return nullptr;
-
- // Returns the string after "=".
- return flag_end + 1;
-}
-
-bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, true);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- // Converts the string value to a bool.
- *value = IsTruthyFlagValue(value_str);
- return true;
-}
-
-bool ParseInt32Flag(const char* str, const char* flag, int32_t* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, false);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- // Sets *value to the value of the flag.
- return ParseInt32(std::string("The value of flag --") + flag, value_str,
- value);
-}
-
-bool ParseDoubleFlag(const char* str, const char* flag, double* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, false);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- // Sets *value to the value of the flag.
- return ParseDouble(std::string("The value of flag --") + flag, value_str,
- value);
-}
-
-bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, false);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- *value = value_str;
- return true;
-}
-
-bool IsFlag(const char* str, const char* flag) {
- return (ParseFlagValue(str, flag, true) != nullptr);
-}
-
-bool IsTruthyFlagValue(const std::string& value) {
- if (value.size() == 1) {
- char v = value[0];
- return isalnum(v) &&
- !(v == '0' || v == 'f' || v == 'F' || v == 'n' || v == 'N');
- } else if (!value.empty()) {
- std::string value_lower(value);
- std::transform(value_lower.begin(), value_lower.end(), value_lower.begin(),
- [](char c) { return static_cast<char>(::tolower(c)); });
- return !(value_lower == "false" || value_lower == "no" ||
- value_lower == "off");
- } else
- return true;
-}
-
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_COMMANDLINEFLAGS_H_
-#define BENCHMARK_COMMANDLINEFLAGS_H_
-
-#include <cstdint>
-#include <string>
-
-// Macro for referencing flags.
-#define FLAG(name) FLAGS_##name
-
-// Macros for declaring flags.
-#define DECLARE_bool(name) extern bool FLAG(name)
-#define DECLARE_int32(name) extern int32_t FLAG(name)
-#define DECLARE_double(name) extern double FLAG(name)
-#define DECLARE_string(name) extern std::string FLAG(name)
-
-// Macros for defining flags.
-#define DEFINE_bool(name, default_val) \
- bool FLAG(name) = \
- benchmark::BoolFromEnv(#name, default_val)
-#define DEFINE_int32(name, default_val) \
- int32_t FLAG(name) = \
- benchmark::Int32FromEnv(#name, default_val)
-#define DEFINE_double(name, default_val) \
- double FLAG(name) = \
- benchmark::DoubleFromEnv(#name, default_val)
-#define DEFINE_string(name, default_val) \
- std::string FLAG(name) = \
- benchmark::StringFromEnv(#name, default_val)
-
-namespace benchmark {
-
-// Parses a bool from the environment variable
-// corresponding to the given flag.
-//
-// If the variable exists, returns IsTruthyFlagValue() value; if not,
-// returns the given default value.
-bool BoolFromEnv(const char* flag, bool default_val);
-
-// Parses an Int32 from the environment variable
-// corresponding to the given flag.
-//
-// If the variable exists, returns ParseInt32() value; if not, returns
-// the given default value.
-int32_t Int32FromEnv(const char* flag, int32_t default_val);
-
-// Parses an Double from the environment variable
-// corresponding to the given flag.
-//
-// If the variable exists, returns ParseDouble(); if not, returns
-// the given default value.
-double DoubleFromEnv(const char* flag, double default_val);
-
-// Parses a string from the environment variable
-// corresponding to the given flag.
-//
-// If variable exists, returns its value; if not, returns
-// the given default value.
-const char* StringFromEnv(const char* flag, const char* default_val);
-
-// Parses a string for a bool flag, in the form of either
-// "--flag=value" or "--flag".
-//
-// In the former case, the value is taken as true if it passes IsTruthyValue().
-//
-// In the latter case, the value is taken as true.
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-bool ParseBoolFlag(const char* str, const char* flag, bool* value);
-
-// Parses a string for an Int32 flag, in the form of
-// "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-bool ParseInt32Flag(const char* str, const char* flag, int32_t* value);
-
-// Parses a string for a Double flag, in the form of
-// "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-bool ParseDoubleFlag(const char* str, const char* flag, double* value);
-
-// Parses a string for a string flag, in the form of
-// "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-bool ParseStringFlag(const char* str, const char* flag, std::string* value);
-
-// Returns true if the string matches the flag.
-bool IsFlag(const char* str, const char* flag);
-
-// Returns true unless value starts with one of: '0', 'f', 'F', 'n' or 'N', or
-// some non-alphanumeric character. Also returns false if the value matches
-// one of 'no', 'false', 'off' (case-insensitive). As a special case, also
-// returns true if value is the empty string.
-bool IsTruthyFlagValue(const std::string& value);
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_COMMANDLINEFLAGS_H_
+++ /dev/null
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Source project : https://github.com/ismaelJimenez/cpp.leastsq
-// Adapted to be used with google benchmark
-
-#include "benchmark/benchmark.h"
-
-#include <algorithm>
-#include <cmath>
-#include "check.h"
-#include "complexity.h"
-
-namespace benchmark {
-
-// Internal function to calculate the different scalability forms
-BigOFunc* FittingCurve(BigO complexity) {
- static const double kLog2E = 1.44269504088896340736;
- switch (complexity) {
- case oN:
- return [](IterationCount n) -> double { return static_cast<double>(n); };
- case oNSquared:
- return [](IterationCount n) -> double { return std::pow(n, 2); };
- case oNCubed:
- return [](IterationCount n) -> double { return std::pow(n, 3); };
- case oLogN:
- /* Note: can't use log2 because Android's GNU STL lacks it */
- return
- [](IterationCount n) { return kLog2E * log(static_cast<double>(n)); };
- case oNLogN:
- /* Note: can't use log2 because Android's GNU STL lacks it */
- return [](IterationCount n) {
- return kLog2E * n * log(static_cast<double>(n));
- };
- case o1:
- default:
- return [](IterationCount) { return 1.0; };
- }
-}
-
-// Function to return an string for the calculated complexity
-std::string GetBigOString(BigO complexity) {
- switch (complexity) {
- case oN:
- return "N";
- case oNSquared:
- return "N^2";
- case oNCubed:
- return "N^3";
- case oLogN:
- return "lgN";
- case oNLogN:
- return "NlgN";
- case o1:
- return "(1)";
- default:
- return "f(N)";
- }
-}
-
-// Find the coefficient for the high-order term in the running time, by
-// minimizing the sum of squares of relative error, for the fitting curve
-// given by the lambda expression.
-// - n : Vector containing the size of the benchmark tests.
-// - time : Vector containing the times for the benchmark tests.
-// - fitting_curve : lambda expression (e.g. [](int64_t n) {return n; };).
-
-// For a deeper explanation on the algorithm logic, please refer to
-// https://en.wikipedia.org/wiki/Least_squares#Least_squares,_regression_analysis_and_statistics
-
-LeastSq MinimalLeastSq(const std::vector<int64_t>& n,
- const std::vector<double>& time,
- BigOFunc* fitting_curve) {
- double sigma_gn = 0.0;
- double sigma_gn_squared = 0.0;
- double sigma_time = 0.0;
- double sigma_time_gn = 0.0;
-
- // Calculate least square fitting parameter
- for (size_t i = 0; i < n.size(); ++i) {
- double gn_i = fitting_curve(n[i]);
- sigma_gn += gn_i;
- sigma_gn_squared += gn_i * gn_i;
- sigma_time += time[i];
- sigma_time_gn += time[i] * gn_i;
- }
-
- LeastSq result;
- result.complexity = oLambda;
-
- // Calculate complexity.
- result.coef = sigma_time_gn / sigma_gn_squared;
-
- // Calculate RMS
- double rms = 0.0;
- for (size_t i = 0; i < n.size(); ++i) {
- double fit = result.coef * fitting_curve(n[i]);
- rms += pow((time[i] - fit), 2);
- }
-
- // Normalized RMS by the mean of the observed values
- double mean = sigma_time / n.size();
- result.rms = sqrt(rms / n.size()) / mean;
-
- return result;
-}
-
-// Find the coefficient for the high-order term in the running time, by
-// minimizing the sum of squares of relative error.
-// - n : Vector containing the size of the benchmark tests.
-// - time : Vector containing the times for the benchmark tests.
-// - complexity : If different than oAuto, the fitting curve will stick to
-// this one. If it is oAuto, it will be calculated the best
-// fitting curve.
-LeastSq MinimalLeastSq(const std::vector<int64_t>& n,
- const std::vector<double>& time, const BigO complexity) {
- CHECK_EQ(n.size(), time.size());
- CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two
- // benchmark runs are given
- CHECK_NE(complexity, oNone);
-
- LeastSq best_fit;
-
- if (complexity == oAuto) {
- std::vector<BigO> fit_curves = {oLogN, oN, oNLogN, oNSquared, oNCubed};
-
- // Take o1 as default best fitting curve
- best_fit = MinimalLeastSq(n, time, FittingCurve(o1));
- best_fit.complexity = o1;
-
- // Compute all possible fitting curves and stick to the best one
- for (const auto& fit : fit_curves) {
- LeastSq current_fit = MinimalLeastSq(n, time, FittingCurve(fit));
- if (current_fit.rms < best_fit.rms) {
- best_fit = current_fit;
- best_fit.complexity = fit;
- }
- }
- } else {
- best_fit = MinimalLeastSq(n, time, FittingCurve(complexity));
- best_fit.complexity = complexity;
- }
-
- return best_fit;
-}
-
-std::vector<BenchmarkReporter::Run> ComputeBigO(
- const std::vector<BenchmarkReporter::Run>& reports) {
- typedef BenchmarkReporter::Run Run;
- std::vector<Run> results;
-
- if (reports.size() < 2) return results;
-
- // Accumulators.
- std::vector<int64_t> n;
- std::vector<double> real_time;
- std::vector<double> cpu_time;
-
- // Populate the accumulators.
- for (const Run& run : reports) {
- CHECK_GT(run.complexity_n, 0) << "Did you forget to call SetComplexityN?";
- n.push_back(run.complexity_n);
- real_time.push_back(run.real_accumulated_time / run.iterations);
- cpu_time.push_back(run.cpu_accumulated_time / run.iterations);
- }
-
- LeastSq result_cpu;
- LeastSq result_real;
-
- if (reports[0].complexity == oLambda) {
- result_cpu = MinimalLeastSq(n, cpu_time, reports[0].complexity_lambda);
- result_real = MinimalLeastSq(n, real_time, reports[0].complexity_lambda);
- } else {
- result_cpu = MinimalLeastSq(n, cpu_time, reports[0].complexity);
- result_real = MinimalLeastSq(n, real_time, result_cpu.complexity);
- }
-
- // Drop the 'args' when reporting complexity.
- auto run_name = reports[0].run_name;
- run_name.args.clear();
-
- // Get the data from the accumulator to BenchmarkReporter::Run's.
- Run big_o;
- big_o.run_name = run_name;
- big_o.run_type = BenchmarkReporter::Run::RT_Aggregate;
- big_o.repetitions = reports[0].repetitions;
- big_o.repetition_index = Run::no_repetition_index;
- big_o.threads = reports[0].threads;
- big_o.aggregate_name = "BigO";
- big_o.report_label = reports[0].report_label;
- big_o.iterations = 0;
- big_o.real_accumulated_time = result_real.coef;
- big_o.cpu_accumulated_time = result_cpu.coef;
- big_o.report_big_o = true;
- big_o.complexity = result_cpu.complexity;
-
- // All the time results are reported after being multiplied by the
- // time unit multiplier. But since RMS is a relative quantity it
- // should not be multiplied at all. So, here, we _divide_ it by the
- // multiplier so that when it is multiplied later the result is the
- // correct one.
- double multiplier = GetTimeUnitMultiplier(reports[0].time_unit);
-
- // Only add label to mean/stddev if it is same for all runs
- Run rms;
- rms.run_name = run_name;
- rms.run_type = BenchmarkReporter::Run::RT_Aggregate;
- rms.aggregate_name = "RMS";
- rms.report_label = big_o.report_label;
- rms.iterations = 0;
- rms.repetition_index = Run::no_repetition_index;
- rms.repetitions = reports[0].repetitions;
- rms.threads = reports[0].threads;
- rms.real_accumulated_time = result_real.rms / multiplier;
- rms.cpu_accumulated_time = result_cpu.rms / multiplier;
- rms.report_rms = true;
- rms.complexity = result_cpu.complexity;
- // don't forget to keep the time unit, or we won't be able to
- // recover the correct value.
- rms.time_unit = reports[0].time_unit;
-
- results.push_back(big_o);
- results.push_back(rms);
- return results;
-}
-
-} // end namespace benchmark
+++ /dev/null
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Source project : https://github.com/ismaelJimenez/cpp.leastsq
-// Adapted to be used with google benchmark
-
-#ifndef COMPLEXITY_H_
-#define COMPLEXITY_H_
-
-#include <string>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-
-// Return a vector containing the bigO and RMS information for the specified
-// list of reports. If 'reports.size() < 2' an empty vector is returned.
-std::vector<BenchmarkReporter::Run> ComputeBigO(
- const std::vector<BenchmarkReporter::Run>& reports);
-
-// This data structure will contain the result returned by MinimalLeastSq
-// - coef : Estimated coeficient for the high-order term as
-// interpolated from data.
-// - rms : Normalized Root Mean Squared Error.
-// - complexity : Scalability form (e.g. oN, oNLogN). In case a scalability
-// form has been provided to MinimalLeastSq this will return
-// the same value. In case BigO::oAuto has been selected, this
-// parameter will return the best fitting curve detected.
-
-struct LeastSq {
- LeastSq() : coef(0.0), rms(0.0), complexity(oNone) {}
-
- double coef;
- double rms;
- BigO complexity;
-};
-
-// Function to return an string for the calculated complexity
-std::string GetBigOString(BigO complexity);
-
-} // end namespace benchmark
-
-#endif // COMPLEXITY_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <algorithm>
-#include <cstdint>
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-#include <string>
-#include <tuple>
-#include <vector>
-
-#include "benchmark/benchmark.h"
-#include "check.h"
-#include "colorprint.h"
-#include "commandlineflags.h"
-#include "complexity.h"
-#include "counter.h"
-#include "internal_macros.h"
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-
-bool ConsoleReporter::ReportContext(const Context& context) {
- name_field_width_ = context.name_field_width;
- printed_header_ = false;
- prev_counters_.clear();
-
- PrintBasicContext(&GetErrorStream(), context);
-
-#ifdef BENCHMARK_OS_WINDOWS
- if ((output_options_ & OO_Color) && &std::cout != &GetOutputStream()) {
- GetErrorStream()
- << "Color printing is only supported for stdout on windows."
- " Disabling color printing\n";
- output_options_ = static_cast< OutputOptions >(output_options_ & ~OO_Color);
- }
-#endif
-
- return true;
-}
-
-void ConsoleReporter::PrintHeader(const Run& run) {
- std::string str = FormatString("%-*s %13s %15s %12s", static_cast<int>(name_field_width_),
- "Benchmark", "Time", "CPU", "Iterations");
- if(!run.counters.empty()) {
- if(output_options_ & OO_Tabular) {
- for(auto const& c : run.counters) {
- str += FormatString(" %10s", c.first.c_str());
- }
- } else {
- str += " UserCounters...";
- }
- }
- std::string line = std::string(str.length(), '-');
- GetOutputStream() << line << "\n" << str << "\n" << line << "\n";
-}
-
-void ConsoleReporter::ReportRuns(const std::vector<Run>& reports) {
- for (const auto& run : reports) {
- // print the header:
- // --- if none was printed yet
- bool print_header = !printed_header_;
- // --- or if the format is tabular and this run
- // has different fields from the prev header
- print_header |= (output_options_ & OO_Tabular) &&
- (!internal::SameNames(run.counters, prev_counters_));
- if (print_header) {
- printed_header_ = true;
- prev_counters_ = run.counters;
- PrintHeader(run);
- }
- // As an alternative to printing the headers like this, we could sort
- // the benchmarks by header and then print. But this would require
- // waiting for the full results before printing, or printing twice.
- PrintRunData(run);
- }
-}
-
-static void IgnoreColorPrint(std::ostream& out, LogColor, const char* fmt,
- ...) {
- va_list args;
- va_start(args, fmt);
- out << FormatString(fmt, args);
- va_end(args);
-}
-
-
-static std::string FormatTime(double time) {
- // Align decimal places...
- if (time < 1.0) {
- return FormatString("%10.3f", time);
- }
- if (time < 10.0) {
- return FormatString("%10.2f", time);
- }
- if (time < 100.0) {
- return FormatString("%10.1f", time);
- }
- return FormatString("%10.0f", time);
-}
-
-void ConsoleReporter::PrintRunData(const Run& result) {
- typedef void(PrinterFn)(std::ostream&, LogColor, const char*, ...);
- auto& Out = GetOutputStream();
- PrinterFn* printer = (output_options_ & OO_Color) ?
- (PrinterFn*)ColorPrintf : IgnoreColorPrint;
- auto name_color =
- (result.report_big_o || result.report_rms) ? COLOR_BLUE : COLOR_GREEN;
- printer(Out, name_color, "%-*s ", name_field_width_,
- result.benchmark_name().c_str());
-
- if (result.error_occurred) {
- printer(Out, COLOR_RED, "ERROR OCCURRED: \'%s\'",
- result.error_message.c_str());
- printer(Out, COLOR_DEFAULT, "\n");
- return;
- }
-
- const double real_time = result.GetAdjustedRealTime();
- const double cpu_time = result.GetAdjustedCPUTime();
- const std::string real_time_str = FormatTime(real_time);
- const std::string cpu_time_str = FormatTime(cpu_time);
-
-
- if (result.report_big_o) {
- std::string big_o = GetBigOString(result.complexity);
- printer(Out, COLOR_YELLOW, "%10.2f %-4s %10.2f %-4s ", real_time, big_o.c_str(),
- cpu_time, big_o.c_str());
- } else if (result.report_rms) {
- printer(Out, COLOR_YELLOW, "%10.0f %-4s %10.0f %-4s ", real_time * 100, "%",
- cpu_time * 100, "%");
- } else {
- const char* timeLabel = GetTimeUnitString(result.time_unit);
- printer(Out, COLOR_YELLOW, "%s %-4s %s %-4s ", real_time_str.c_str(), timeLabel,
- cpu_time_str.c_str(), timeLabel);
- }
-
- if (!result.report_big_o && !result.report_rms) {
- printer(Out, COLOR_CYAN, "%10lld", result.iterations);
- }
-
- for (auto& c : result.counters) {
- const std::size_t cNameLen = std::max(std::string::size_type(10),
- c.first.length());
- auto const& s = HumanReadableNumber(c.second.value, c.second.oneK);
- const char* unit = "";
- if (c.second.flags & Counter::kIsRate)
- unit = (c.second.flags & Counter::kInvert) ? "s" : "/s";
- if (output_options_ & OO_Tabular) {
- printer(Out, COLOR_DEFAULT, " %*s%s", cNameLen - strlen(unit), s.c_str(),
- unit);
- } else {
- printer(Out, COLOR_DEFAULT, " %s=%s%s", c.first.c_str(), s.c_str(), unit);
- }
- }
-
- if (!result.report_label.empty()) {
- printer(Out, COLOR_DEFAULT, " %s", result.report_label.c_str());
- }
-
- printer(Out, COLOR_DEFAULT, "\n");
-}
-
-} // end namespace benchmark
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "counter.h"
-
-namespace benchmark {
-namespace internal {
-
-double Finish(Counter const& c, IterationCount iterations, double cpu_time,
- double num_threads) {
- double v = c.value;
- if (c.flags & Counter::kIsRate) {
- v /= cpu_time;
- }
- if (c.flags & Counter::kAvgThreads) {
- v /= num_threads;
- }
- if (c.flags & Counter::kIsIterationInvariant) {
- v *= iterations;
- }
- if (c.flags & Counter::kAvgIterations) {
- v /= iterations;
- }
-
- if (c.flags & Counter::kInvert) { // Invert is *always* last.
- v = 1.0 / v;
- }
- return v;
-}
-
-void Finish(UserCounters* l, IterationCount iterations, double cpu_time,
- double num_threads) {
- for (auto& c : *l) {
- c.second.value = Finish(c.second, iterations, cpu_time, num_threads);
- }
-}
-
-void Increment(UserCounters* l, UserCounters const& r) {
- // add counters present in both or just in *l
- for (auto& c : *l) {
- auto it = r.find(c.first);
- if (it != r.end()) {
- c.second.value = c.second + it->second;
- }
- }
- // add counters present in r, but not in *l
- for (auto const& tc : r) {
- auto it = l->find(tc.first);
- if (it == l->end()) {
- (*l)[tc.first] = tc.second;
- }
- }
-}
-
-bool SameNames(UserCounters const& l, UserCounters const& r) {
- if (&l == &r) return true;
- if (l.size() != r.size()) {
- return false;
- }
- for (auto const& c : l) {
- if (r.find(c.first) == r.end()) {
- return false;
- }
- }
- return true;
-}
-
-} // end namespace internal
-} // end namespace benchmark
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_COUNTER_H_
-#define BENCHMARK_COUNTER_H_
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-
-// these counter-related functions are hidden to reduce API surface.
-namespace internal {
-void Finish(UserCounters* l, IterationCount iterations, double time,
- double num_threads);
-void Increment(UserCounters* l, UserCounters const& r);
-bool SameNames(UserCounters const& l, UserCounters const& r);
-} // end namespace internal
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_COUNTER_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-#include "complexity.h"
-
-#include <algorithm>
-#include <cstdint>
-#include <iostream>
-#include <string>
-#include <tuple>
-#include <vector>
-
-#include "check.h"
-#include "string_util.h"
-#include "timers.h"
-
-// File format reference: http://edoceo.com/utilitas/csv-file-format.
-
-namespace benchmark {
-
-namespace {
-std::vector<std::string> elements = {
- "name", "iterations", "real_time", "cpu_time",
- "time_unit", "bytes_per_second", "items_per_second", "label",
- "error_occurred", "error_message"};
-} // namespace
-
-std::string CsvEscape(const std::string & s) {
- std::string tmp;
- tmp.reserve(s.size() + 2);
- for (char c : s) {
- switch (c) {
- case '"' : tmp += "\"\""; break;
- default : tmp += c; break;
- }
- }
- return '"' + tmp + '"';
-}
-
-bool CSVReporter::ReportContext(const Context& context) {
- PrintBasicContext(&GetErrorStream(), context);
- return true;
-}
-
-void CSVReporter::ReportRuns(const std::vector<Run>& reports) {
- std::ostream& Out = GetOutputStream();
-
- if (!printed_header_) {
- // save the names of all the user counters
- for (const auto& run : reports) {
- for (const auto& cnt : run.counters) {
- if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second")
- continue;
- user_counter_names_.insert(cnt.first);
- }
- }
-
- // print the header
- for (auto B = elements.begin(); B != elements.end();) {
- Out << *B++;
- if (B != elements.end()) Out << ",";
- }
- for (auto B = user_counter_names_.begin();
- B != user_counter_names_.end();) {
- Out << ",\"" << *B++ << "\"";
- }
- Out << "\n";
-
- printed_header_ = true;
- } else {
- // check that all the current counters are saved in the name set
- for (const auto& run : reports) {
- for (const auto& cnt : run.counters) {
- if (cnt.first == "bytes_per_second" || cnt.first == "items_per_second")
- continue;
- CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end())
- << "All counters must be present in each run. "
- << "Counter named \"" << cnt.first
- << "\" was not in a run after being added to the header";
- }
- }
- }
-
- // print results for each run
- for (const auto& run : reports) {
- PrintRunData(run);
- }
-}
-
-void CSVReporter::PrintRunData(const Run& run) {
- std::ostream& Out = GetOutputStream();
- Out << CsvEscape(run.benchmark_name()) << ",";
- if (run.error_occurred) {
- Out << std::string(elements.size() - 3, ',');
- Out << "true,";
- Out << CsvEscape(run.error_message) << "\n";
- return;
- }
-
- // Do not print iteration on bigO and RMS report
- if (!run.report_big_o && !run.report_rms) {
- Out << run.iterations;
- }
- Out << ",";
-
- Out << run.GetAdjustedRealTime() << ",";
- Out << run.GetAdjustedCPUTime() << ",";
-
- // Do not print timeLabel on bigO and RMS report
- if (run.report_big_o) {
- Out << GetBigOString(run.complexity);
- } else if (!run.report_rms) {
- Out << GetTimeUnitString(run.time_unit);
- }
- Out << ",";
-
- if (run.counters.find("bytes_per_second") != run.counters.end()) {
- Out << run.counters.at("bytes_per_second");
- }
- Out << ",";
- if (run.counters.find("items_per_second") != run.counters.end()) {
- Out << run.counters.at("items_per_second");
- }
- Out << ",";
- if (!run.report_label.empty()) {
- Out << CsvEscape(run.report_label);
- }
- Out << ",,"; // for error_occurred and error_message
-
- // Print user counters
- for (const auto& ucn : user_counter_names_) {
- auto it = run.counters.find(ucn);
- if (it == run.counters.end()) {
- Out << ",";
- } else {
- Out << "," << it->second;
- }
- }
- Out << '\n';
-}
-
-} // end namespace benchmark
+++ /dev/null
-// ----------------------------------------------------------------------
-// CycleClock
-// A CycleClock tells you the current time in Cycles. The "time"
-// is actually time since power-on. This is like time() but doesn't
-// involve a system call and is much more precise.
-//
-// NOTE: Not all cpu/platform/kernel combinations guarantee that this
-// clock increments at a constant rate or is synchronized across all logical
-// cpus in a system.
-//
-// If you need the above guarantees, please consider using a different
-// API. There are efforts to provide an interface which provides a millisecond
-// granularity and implemented as a memory read. A memory read is generally
-// cheaper than the CycleClock for many architectures.
-//
-// Also, in some out of order CPU implementations, the CycleClock is not
-// serializing. So if you're trying to count at cycles granularity, your
-// data might be inaccurate due to out of order instruction execution.
-// ----------------------------------------------------------------------
-
-#ifndef BENCHMARK_CYCLECLOCK_H_
-#define BENCHMARK_CYCLECLOCK_H_
-
-#include <cstdint>
-
-#include "benchmark/benchmark.h"
-#include "internal_macros.h"
-
-#if defined(BENCHMARK_OS_MACOSX)
-#include <mach/mach_time.h>
-#endif
-// For MSVC, we want to use '_asm rdtsc' when possible (since it works
-// with even ancient MSVC compilers), and when not possible the
-// __rdtsc intrinsic, declared in <intrin.h>. Unfortunately, in some
-// environments, <windows.h> and <intrin.h> have conflicting
-// declarations of some other intrinsics, breaking compilation.
-// Therefore, we simply declare __rdtsc ourselves. See also
-// http://connect.microsoft.com/VisualStudio/feedback/details/262047
-#if defined(COMPILER_MSVC) && !defined(_M_IX86)
-extern "C" uint64_t __rdtsc();
-#pragma intrinsic(__rdtsc)
-#endif
-
-#if !defined(BENCHMARK_OS_WINDOWS) || defined(BENCHMARK_OS_MINGW)
-#include <sys/time.h>
-#include <time.h>
-#endif
-
-#ifdef BENCHMARK_OS_EMSCRIPTEN
-#include <emscripten.h>
-#endif
-
-namespace benchmark {
-// NOTE: only i386 and x86_64 have been well tested.
-// PPC, sparc, alpha, and ia64 are based on
-// http://peter.kuscsik.com/wordpress/?p=14
-// with modifications by m3b. See also
-// https://setisvn.ssl.berkeley.edu/svn/lib/fftw-3.0.1/kernel/cycle.h
-namespace cycleclock {
-// This should return the number of cycles since power-on. Thread-safe.
-inline BENCHMARK_ALWAYS_INLINE int64_t Now() {
-#if defined(BENCHMARK_OS_MACOSX)
- // this goes at the top because we need ALL Macs, regardless of
- // architecture, to return the number of "mach time units" that
- // have passed since startup. See sysinfo.cc where
- // InitializeSystemInfo() sets the supposed cpu clock frequency of
- // macs to the number of mach time units per second, not actual
- // CPU clock frequency (which can change in the face of CPU
- // frequency scaling). Also note that when the Mac sleeps, this
- // counter pauses; it does not continue counting, nor does it
- // reset to zero.
- return mach_absolute_time();
-#elif defined(BENCHMARK_OS_EMSCRIPTEN)
- // this goes above x86-specific code because old versions of Emscripten
- // define __x86_64__, although they have nothing to do with it.
- return static_cast<int64_t>(emscripten_get_now() * 1e+6);
-#elif defined(__i386__)
- int64_t ret;
- __asm__ volatile("rdtsc" : "=A"(ret));
- return ret;
-#elif defined(__x86_64__) || defined(__amd64__)
- uint64_t low, high;
- __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
- return (high << 32) | low;
-#elif defined(__powerpc__) || defined(__ppc__)
- // This returns a time-base, which is not always precisely a cycle-count.
-#if defined(__powerpc64__) || defined(__ppc64__)
- int64_t tb;
- asm volatile("mfspr %0, 268" : "=r"(tb));
- return tb;
-#else
- uint32_t tbl, tbu0, tbu1;
- asm volatile(
- "mftbu %0\n"
- "mftbl %1\n"
- "mftbu %2"
- : "=r"(tbu0), "=r"(tbl), "=r"(tbu1));
- tbl &= -static_cast<int32_t>(tbu0 == tbu1);
- // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is no longer needed)
- return (static_cast<uint64_t>(tbu1) << 32) | tbl;
-#endif
-#elif defined(__sparc__)
- int64_t tick;
- asm(".byte 0x83, 0x41, 0x00, 0x00");
- asm("mov %%g1, %0" : "=r"(tick));
- return tick;
-#elif defined(__ia64__)
- int64_t itc;
- asm("mov %0 = ar.itc" : "=r"(itc));
- return itc;
-#elif defined(COMPILER_MSVC) && defined(_M_IX86)
- // Older MSVC compilers (like 7.x) don't seem to support the
- // __rdtsc intrinsic properly, so I prefer to use _asm instead
- // when I know it will work. Otherwise, I'll use __rdtsc and hope
- // the code is being compiled with a non-ancient compiler.
- _asm rdtsc
-#elif defined(COMPILER_MSVC)
- return __rdtsc();
-#elif defined(BENCHMARK_OS_NACL)
- // Native Client validator on x86/x86-64 allows RDTSC instructions,
- // and this case is handled above. Native Client validator on ARM
- // rejects MRC instructions (used in the ARM-specific sequence below),
- // so we handle it here. Portable Native Client compiles to
- // architecture-agnostic bytecode, which doesn't provide any
- // cycle counter access mnemonics.
-
- // Native Client does not provide any API to access cycle counter.
- // Use clock_gettime(CLOCK_MONOTONIC, ...) instead of gettimeofday
- // because is provides nanosecond resolution (which is noticable at
- // least for PNaCl modules running on x86 Mac & Linux).
- // Initialize to always return 0 if clock_gettime fails.
- struct timespec ts = {0, 0};
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return static_cast<int64_t>(ts.tv_sec) * 1000000000 + ts.tv_nsec;
-#elif defined(__aarch64__)
- // System timer of ARMv8 runs at a different frequency than the CPU's.
- // The frequency is fixed, typically in the range 1-50MHz. It can be
- // read at CNTFRQ special register. We assume the OS has set up
- // the virtual timer properly.
- int64_t virtual_timer_value;
- asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
- return virtual_timer_value;
-#elif defined(__ARM_ARCH)
- // V6 is the earliest arch that has a standard cyclecount
- // Native Client validator doesn't allow MRC instructions.
-#if (__ARM_ARCH >= 6)
- uint32_t pmccntr;
- uint32_t pmuseren;
- uint32_t pmcntenset;
- // Read the user mode perf monitor counter access permissions.
- asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(pmuseren));
- if (pmuseren & 1) { // Allows reading perfmon counters for user mode code.
- asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcntenset));
- if (pmcntenset & 0x80000000ul) { // Is it counting?
- asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr));
- // The counter is set up to count every 64th cycle
- return static_cast<int64_t>(pmccntr) * 64; // Should optimize to << 6
- }
- }
-#endif
- struct timeval tv;
- gettimeofday(&tv, nullptr);
- return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__mips__)
- // mips apparently only allows rdtsc for superusers, so we fall
- // back to gettimeofday. It's possible clock_gettime would be better.
- struct timeval tv;
- gettimeofday(&tv, nullptr);
- return static_cast<int64_t>(tv.tv_sec) * 1000000 + tv.tv_usec;
-#elif defined(__s390__) // Covers both s390 and s390x.
- // Return the CPU clock.
- uint64_t tsc;
- asm("stck %0" : "=Q"(tsc) : : "cc");
- return tsc;
-#elif defined(__riscv) // RISC-V
- // Use RDCYCLE (and RDCYCLEH on riscv32)
-#if __riscv_xlen == 32
- uint32_t cycles_lo, cycles_hi0, cycles_hi1;
- // This asm also includes the PowerPC overflow handling strategy, as above.
- // Implemented in assembly because Clang insisted on branching.
- asm volatile(
- "rdcycleh %0\n"
- "rdcycle %1\n"
- "rdcycleh %2\n"
- "sub %0, %0, %2\n"
- "seqz %0, %0\n"
- "sub %0, zero, %0\n"
- "and %1, %1, %0\n"
- : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
- return (static_cast<uint64_t>(cycles_hi1) << 32) | cycles_lo;
-#else
- uint64_t cycles;
- asm volatile("rdcycle %0" : "=r"(cycles));
- return cycles;
-#endif
-#else
-// The soft failover to a generic implementation is automatic only for ARM.
-// For other platforms the developer is expected to make an attempt to create
-// a fast implementation and use generic version if nothing better is available.
-#error You need to define CycleTimer for your OS and CPU
-#endif
-}
-} // end namespace cycleclock
-} // end namespace benchmark
-
-#endif // BENCHMARK_CYCLECLOCK_H_
+++ /dev/null
-#ifndef BENCHMARK_INTERNAL_MACROS_H_
-#define BENCHMARK_INTERNAL_MACROS_H_
-
-#include "benchmark/benchmark.h"
-
-/* Needed to detect STL */
-#include <cstdlib>
-
-// clang-format off
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-#if defined(__clang__)
- #if !defined(COMPILER_CLANG)
- #define COMPILER_CLANG
- #endif
-#elif defined(_MSC_VER)
- #if !defined(COMPILER_MSVC)
- #define COMPILER_MSVC
- #endif
-#elif defined(__GNUC__)
- #if !defined(COMPILER_GCC)
- #define COMPILER_GCC
- #endif
-#endif
-
-#if __has_feature(cxx_attributes)
- #define BENCHMARK_NORETURN [[noreturn]]
-#elif defined(__GNUC__)
- #define BENCHMARK_NORETURN __attribute__((noreturn))
-#elif defined(COMPILER_MSVC)
- #define BENCHMARK_NORETURN __declspec(noreturn)
-#else
- #define BENCHMARK_NORETURN
-#endif
-
-#if defined(__CYGWIN__)
- #define BENCHMARK_OS_CYGWIN 1
-#elif defined(_WIN32)
- #define BENCHMARK_OS_WINDOWS 1
- #if defined(__MINGW32__)
- #define BENCHMARK_OS_MINGW 1
- #endif
-#elif defined(__APPLE__)
- #define BENCHMARK_OS_APPLE 1
- #include "TargetConditionals.h"
- #if defined(TARGET_OS_MAC)
- #define BENCHMARK_OS_MACOSX 1
- #if defined(TARGET_OS_IPHONE)
- #define BENCHMARK_OS_IOS 1
- #endif
- #endif
-#elif defined(__FreeBSD__)
- #define BENCHMARK_OS_FREEBSD 1
-#elif defined(__NetBSD__)
- #define BENCHMARK_OS_NETBSD 1
-#elif defined(__OpenBSD__)
- #define BENCHMARK_OS_OPENBSD 1
-#elif defined(__linux__)
- #define BENCHMARK_OS_LINUX 1
-#elif defined(__native_client__)
- #define BENCHMARK_OS_NACL 1
-#elif defined(__EMSCRIPTEN__)
- #define BENCHMARK_OS_EMSCRIPTEN 1
-#elif defined(__rtems__)
- #define BENCHMARK_OS_RTEMS 1
-#elif defined(__Fuchsia__)
-#define BENCHMARK_OS_FUCHSIA 1
-#elif defined (__SVR4) && defined (__sun)
-#define BENCHMARK_OS_SOLARIS 1
-#elif defined(__QNX__)
-#define BENCHMARK_OS_QNX 1
-#endif
-
-#if defined(__ANDROID__) && defined(__GLIBCXX__)
-#define BENCHMARK_STL_ANDROID_GNUSTL 1
-#endif
-
-#if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \
- && !defined(__EXCEPTIONS)
- #define BENCHMARK_HAS_NO_EXCEPTIONS
-#endif
-
-#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
- #define BENCHMARK_MAYBE_UNUSED __attribute__((unused))
-#else
- #define BENCHMARK_MAYBE_UNUSED
-#endif
-
-// clang-format on
-
-#endif // BENCHMARK_INTERNAL_MACROS_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-#include "complexity.h"
-
-#include <algorithm>
-#include <cmath>
-#include <cstdint>
-#include <iomanip> // for setprecision
-#include <iostream>
-#include <limits>
-#include <string>
-#include <tuple>
-#include <vector>
-
-#include "string_util.h"
-#include "timers.h"
-
-namespace benchmark {
-
-namespace {
-
-std::string StrEscape(const std::string & s) {
- std::string tmp;
- tmp.reserve(s.size());
- for (char c : s) {
- switch (c) {
- case '\b': tmp += "\\b"; break;
- case '\f': tmp += "\\f"; break;
- case '\n': tmp += "\\n"; break;
- case '\r': tmp += "\\r"; break;
- case '\t': tmp += "\\t"; break;
- case '\\': tmp += "\\\\"; break;
- case '"' : tmp += "\\\""; break;
- default : tmp += c; break;
- }
- }
- return tmp;
-}
-
-std::string FormatKV(std::string const& key, std::string const& value) {
- return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(), StrEscape(value).c_str());
-}
-
-std::string FormatKV(std::string const& key, const char* value) {
- return StrFormat("\"%s\": \"%s\"", StrEscape(key).c_str(), StrEscape(value).c_str());
-}
-
-std::string FormatKV(std::string const& key, bool value) {
- return StrFormat("\"%s\": %s", StrEscape(key).c_str(), value ? "true" : "false");
-}
-
-std::string FormatKV(std::string const& key, int64_t value) {
- std::stringstream ss;
- ss << '"' << StrEscape(key) << "\": " << value;
- return ss.str();
-}
-
-std::string FormatKV(std::string const& key, IterationCount value) {
- std::stringstream ss;
- ss << '"' << StrEscape(key) << "\": " << value;
- return ss.str();
-}
-
-std::string FormatKV(std::string const& key, double value) {
- std::stringstream ss;
- ss << '"' << StrEscape(key) << "\": ";
-
- if (std::isnan(value))
- ss << (value < 0 ? "-" : "") << "NaN";
- else if (std::isinf(value))
- ss << (value < 0 ? "-" : "") << "Infinity";
- else {
- const auto max_digits10 =
- std::numeric_limits<decltype(value)>::max_digits10;
- const auto max_fractional_digits10 = max_digits10 - 1;
- ss << std::scientific << std::setprecision(max_fractional_digits10)
- << value;
- }
- return ss.str();
-}
-
-int64_t RoundDouble(double v) { return std::lround(v); }
-
-} // end namespace
-
-bool JSONReporter::ReportContext(const Context& context) {
- std::ostream& out = GetOutputStream();
-
- out << "{\n";
- std::string inner_indent(2, ' ');
-
- // Open context block and print context information.
- out << inner_indent << "\"context\": {\n";
- std::string indent(4, ' ');
-
- std::string walltime_value = LocalDateTimeString();
- out << indent << FormatKV("date", walltime_value) << ",\n";
-
- out << indent << FormatKV("host_name", context.sys_info.name) << ",\n";
-
- if (Context::executable_name) {
- out << indent << FormatKV("executable", Context::executable_name) << ",\n";
- }
-
- CPUInfo const& info = context.cpu_info;
- out << indent << FormatKV("num_cpus", static_cast<int64_t>(info.num_cpus))
- << ",\n";
- out << indent
- << FormatKV("mhz_per_cpu",
- RoundDouble(info.cycles_per_second / 1000000.0))
- << ",\n";
- out << indent << FormatKV("cpu_scaling_enabled", info.scaling_enabled)
- << ",\n";
-
- out << indent << "\"caches\": [\n";
- indent = std::string(6, ' ');
- std::string cache_indent(8, ' ');
- for (size_t i = 0; i < info.caches.size(); ++i) {
- auto& CI = info.caches[i];
- out << indent << "{\n";
- out << cache_indent << FormatKV("type", CI.type) << ",\n";
- out << cache_indent << FormatKV("level", static_cast<int64_t>(CI.level))
- << ",\n";
- out << cache_indent
- << FormatKV("size", static_cast<int64_t>(CI.size)) << ",\n";
- out << cache_indent
- << FormatKV("num_sharing", static_cast<int64_t>(CI.num_sharing))
- << "\n";
- out << indent << "}";
- if (i != info.caches.size() - 1) out << ",";
- out << "\n";
- }
- indent = std::string(4, ' ');
- out << indent << "],\n";
- out << indent << "\"load_avg\": [";
- for (auto it = info.load_avg.begin(); it != info.load_avg.end();) {
- out << *it++;
- if (it != info.load_avg.end()) out << ",";
- }
- out << "],\n";
-
-#if defined(NDEBUG)
- const char build_type[] = "release";
-#else
- const char build_type[] = "debug";
-#endif
- out << indent << FormatKV("library_build_type", build_type) << "\n";
- // Close context block and open the list of benchmarks.
- out << inner_indent << "},\n";
- out << inner_indent << "\"benchmarks\": [\n";
- return true;
-}
-
-void JSONReporter::ReportRuns(std::vector<Run> const& reports) {
- if (reports.empty()) {
- return;
- }
- std::string indent(4, ' ');
- std::ostream& out = GetOutputStream();
- if (!first_report_) {
- out << ",\n";
- }
- first_report_ = false;
-
- for (auto it = reports.begin(); it != reports.end(); ++it) {
- out << indent << "{\n";
- PrintRunData(*it);
- out << indent << '}';
- auto it_cp = it;
- if (++it_cp != reports.end()) {
- out << ",\n";
- }
- }
-}
-
-void JSONReporter::Finalize() {
- // Close the list of benchmarks and the top level object.
- GetOutputStream() << "\n ]\n}\n";
-}
-
-void JSONReporter::PrintRunData(Run const& run) {
- std::string indent(6, ' ');
- std::ostream& out = GetOutputStream();
- out << indent << FormatKV("name", run.benchmark_name()) << ",\n";
- out << indent << FormatKV("run_name", run.run_name.str()) << ",\n";
- out << indent << FormatKV("run_type", [&run]() -> const char* {
- switch (run.run_type) {
- case BenchmarkReporter::Run::RT_Iteration:
- return "iteration";
- case BenchmarkReporter::Run::RT_Aggregate:
- return "aggregate";
- }
- BENCHMARK_UNREACHABLE();
- }()) << ",\n";
- out << indent << FormatKV("repetitions", run.repetitions) << ",\n";
- if (run.run_type != BenchmarkReporter::Run::RT_Aggregate) {
- out << indent << FormatKV("repetition_index", run.repetition_index)
- << ",\n";
- }
- out << indent << FormatKV("threads", run.threads) << ",\n";
- if (run.run_type == BenchmarkReporter::Run::RT_Aggregate) {
- out << indent << FormatKV("aggregate_name", run.aggregate_name) << ",\n";
- }
- if (run.error_occurred) {
- out << indent << FormatKV("error_occurred", run.error_occurred) << ",\n";
- out << indent << FormatKV("error_message", run.error_message) << ",\n";
- }
- if (!run.report_big_o && !run.report_rms) {
- out << indent << FormatKV("iterations", run.iterations) << ",\n";
- out << indent << FormatKV("real_time", run.GetAdjustedRealTime()) << ",\n";
- out << indent << FormatKV("cpu_time", run.GetAdjustedCPUTime());
- out << ",\n"
- << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
- } else if (run.report_big_o) {
- out << indent << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime())
- << ",\n";
- out << indent << FormatKV("real_coefficient", run.GetAdjustedRealTime())
- << ",\n";
- out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n";
- out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit));
- } else if (run.report_rms) {
- out << indent << FormatKV("rms", run.GetAdjustedCPUTime());
- }
-
- for (auto& c : run.counters) {
- out << ",\n" << indent << FormatKV(c.first, c.second);
- }
-
- if (run.has_memory_result) {
- out << ",\n" << indent << FormatKV("allocs_per_iter", run.allocs_per_iter);
- out << ",\n" << indent << FormatKV("max_bytes_used", run.max_bytes_used);
- }
-
- if (!run.report_label.empty()) {
- out << ",\n" << indent << FormatKV("label", run.report_label);
- }
- out << '\n';
-}
-
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_LOG_H_
-#define BENCHMARK_LOG_H_
-
-#include <iostream>
-#include <ostream>
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-namespace internal {
-
-typedef std::basic_ostream<char>&(EndLType)(std::basic_ostream<char>&);
-
-class LogType {
- friend LogType& GetNullLogInstance();
- friend LogType& GetErrorLogInstance();
-
- // FIXME: Add locking to output.
- template <class Tp>
- friend LogType& operator<<(LogType&, Tp const&);
- friend LogType& operator<<(LogType&, EndLType*);
-
- private:
- LogType(std::ostream* out) : out_(out) {}
- std::ostream* out_;
- BENCHMARK_DISALLOW_COPY_AND_ASSIGN(LogType);
-};
-
-template <class Tp>
-LogType& operator<<(LogType& log, Tp const& value) {
- if (log.out_) {
- *log.out_ << value;
- }
- return log;
-}
-
-inline LogType& operator<<(LogType& log, EndLType* m) {
- if (log.out_) {
- *log.out_ << m;
- }
- return log;
-}
-
-inline int& LogLevel() {
- static int log_level = 0;
- return log_level;
-}
-
-inline LogType& GetNullLogInstance() {
- static LogType log(nullptr);
- return log;
-}
-
-inline LogType& GetErrorLogInstance() {
- static LogType log(&std::clog);
- return log;
-}
-
-inline LogType& GetLogInstanceForLevel(int level) {
- if (level <= LogLevel()) {
- return GetErrorLogInstance();
- }
- return GetNullLogInstance();
-}
-
-} // end namespace internal
-} // end namespace benchmark
-
-// clang-format off
-#define VLOG(x) \
- (::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \
- " ")
-// clang-format on
-#endif
+++ /dev/null
-#ifndef BENCHMARK_MUTEX_H_
-#define BENCHMARK_MUTEX_H_
-
-#include <condition_variable>
-#include <mutex>
-
-#include "check.h"
-
-// Enable thread safety attributes only with clang.
-// The attributes can be safely erased when compiling with other compilers.
-#if defined(HAVE_THREAD_SAFETY_ATTRIBUTES)
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
-#else
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
-#endif
-
-#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
-
-#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
-
-#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
-
-#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
-
-#define ACQUIRED_BEFORE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
-
-#define ACQUIRED_AFTER(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
-
-#define REQUIRES(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
-
-#define REQUIRES_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
-
-#define ACQUIRE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
-
-#define ACQUIRE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
-
-#define RELEASE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
-
-#define RELEASE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
-
-#define TRY_ACQUIRE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
-
-#define TRY_ACQUIRE_SHARED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
-
-#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
-
-#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
-
-#define ASSERT_SHARED_CAPABILITY(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
-
-#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
-
-#define NO_THREAD_SAFETY_ANALYSIS \
- THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
-
-namespace benchmark {
-
-typedef std::condition_variable Condition;
-
-// NOTE: Wrappers for std::mutex and std::unique_lock are provided so that
-// we can annotate them with thread safety attributes and use the
-// -Wthread-safety warning with clang. The standard library types cannot be
-// used directly because they do not provide the required annotations.
-class CAPABILITY("mutex") Mutex {
- public:
- Mutex() {}
-
- void lock() ACQUIRE() { mut_.lock(); }
- void unlock() RELEASE() { mut_.unlock(); }
- std::mutex& native_handle() { return mut_; }
-
- private:
- std::mutex mut_;
-};
-
-class SCOPED_CAPABILITY MutexLock {
- typedef std::unique_lock<std::mutex> MutexLockImp;
-
- public:
- MutexLock(Mutex& m) ACQUIRE(m) : ml_(m.native_handle()) {}
- ~MutexLock() RELEASE() {}
- MutexLockImp& native_handle() { return ml_; }
-
- private:
- MutexLockImp ml_;
-};
-
-class Barrier {
- public:
- Barrier(int num_threads) : running_threads_(num_threads) {}
-
- // Called by each thread
- bool wait() EXCLUDES(lock_) {
- bool last_thread = false;
- {
- MutexLock ml(lock_);
- last_thread = createBarrier(ml);
- }
- if (last_thread) phase_condition_.notify_all();
- return last_thread;
- }
-
- void removeThread() EXCLUDES(lock_) {
- MutexLock ml(lock_);
- --running_threads_;
- if (entered_ != 0) phase_condition_.notify_all();
- }
-
- private:
- Mutex lock_;
- Condition phase_condition_;
- int running_threads_;
-
- // State for barrier management
- int phase_number_ = 0;
- int entered_ = 0; // Number of threads that have entered this barrier
-
- // Enter the barrier and wait until all other threads have also
- // entered the barrier. Returns iff this is the last thread to
- // enter the barrier.
- bool createBarrier(MutexLock& ml) REQUIRES(lock_) {
- CHECK_LT(entered_, running_threads_);
- entered_++;
- if (entered_ < running_threads_) {
- // Wait for all threads to enter
- int phase_number_cp = phase_number_;
- auto cb = [this, phase_number_cp]() {
- return this->phase_number_ > phase_number_cp ||
- entered_ == running_threads_; // A thread has aborted in error
- };
- phase_condition_.wait(ml.native_handle(), cb);
- if (phase_number_ > phase_number_cp) return false;
- // else (running_threads_ == entered_) and we are the last thread.
- }
- // Last thread has reached the barrier
- phase_number_++;
- entered_ = 0;
- return true;
- }
-};
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_MUTEX_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef BENCHMARK_RE_H_
-#define BENCHMARK_RE_H_
-
-#include "internal_macros.h"
-
-// clang-format off
-
-#if !defined(HAVE_STD_REGEX) && \
- !defined(HAVE_GNU_POSIX_REGEX) && \
- !defined(HAVE_POSIX_REGEX)
- // No explicit regex selection; detect based on builtin hints.
- #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE)
- #define HAVE_POSIX_REGEX 1
- #elif __cplusplus >= 199711L
- #define HAVE_STD_REGEX 1
- #endif
-#endif
-
-// Prefer C regex libraries when compiling w/o exceptions so that we can
-// correctly report errors.
-#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \
- defined(BENCHMARK_HAVE_STD_REGEX) && \
- (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX))
- #undef HAVE_STD_REGEX
-#endif
-
-#if defined(HAVE_STD_REGEX)
- #include <regex>
-#elif defined(HAVE_GNU_POSIX_REGEX)
- #include <gnuregex.h>
-#elif defined(HAVE_POSIX_REGEX)
- #include <regex.h>
-#else
-#error No regular expression backend was found!
-#endif
-
-// clang-format on
-
-#include <string>
-
-#include "check.h"
-
-namespace benchmark {
-
-// A wrapper around the POSIX regular expression API that provides automatic
-// cleanup
-class Regex {
- public:
- Regex() : init_(false) {}
-
- ~Regex();
-
- // Compile a regular expression matcher from spec. Returns true on success.
- //
- // On failure (and if error is not nullptr), error is populated with a human
- // readable error message if an error occurs.
- bool Init(const std::string& spec, std::string* error);
-
- // Returns whether str matches the compiled regular expression.
- bool Match(const std::string& str);
-
- private:
- bool init_;
-// Underlying regular expression object
-#if defined(HAVE_STD_REGEX)
- std::regex re_;
-#elif defined(HAVE_POSIX_REGEX) || defined(HAVE_GNU_POSIX_REGEX)
- regex_t re_;
-#else
-#error No regular expression backend implementation available
-#endif
-};
-
-#if defined(HAVE_STD_REGEX)
-
-inline bool Regex::Init(const std::string& spec, std::string* error) {
-#ifdef BENCHMARK_HAS_NO_EXCEPTIONS
- ((void)error); // suppress unused warning
-#else
- try {
-#endif
- re_ = std::regex(spec, std::regex_constants::extended);
- init_ = true;
-#ifndef BENCHMARK_HAS_NO_EXCEPTIONS
-}
-catch (const std::regex_error& e) {
- if (error) {
- *error = e.what();
- }
-}
-#endif
-return init_;
-}
-
-inline Regex::~Regex() {}
-
-inline bool Regex::Match(const std::string& str) {
- if (!init_) {
- return false;
- }
- return std::regex_search(str, re_);
-}
-
-#else
-inline bool Regex::Init(const std::string& spec, std::string* error) {
- int ec = regcomp(&re_, spec.c_str(), REG_EXTENDED | REG_NOSUB);
- if (ec != 0) {
- if (error) {
- size_t needed = regerror(ec, &re_, nullptr, 0);
- char* errbuf = new char[needed];
- regerror(ec, &re_, errbuf, needed);
-
- // regerror returns the number of bytes necessary to null terminate
- // the string, so we move that when assigning to error.
- CHECK_NE(needed, 0);
- error->assign(errbuf, needed - 1);
-
- delete[] errbuf;
- }
-
- return false;
- }
-
- init_ = true;
- return true;
-}
-
-inline Regex::~Regex() {
- if (init_) {
- regfree(&re_);
- }
-}
-
-inline bool Regex::Match(const std::string& str) {
- if (!init_) {
- return false;
- }
- return regexec(&re_, str.c_str(), 0, nullptr, 0) == 0;
-}
-#endif
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_RE_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-#include "timers.h"
-
-#include <cstdlib>
-
-#include <iostream>
-#include <tuple>
-#include <vector>
-
-#include "check.h"
-#include "string_util.h"
-
-namespace benchmark {
-
-BenchmarkReporter::BenchmarkReporter()
- : output_stream_(&std::cout), error_stream_(&std::cerr) {}
-
-BenchmarkReporter::~BenchmarkReporter() {}
-
-void BenchmarkReporter::PrintBasicContext(std::ostream *out,
- Context const &context) {
- CHECK(out) << "cannot be null";
- auto &Out = *out;
-
- Out << LocalDateTimeString() << "\n";
-
- if (context.executable_name)
- Out << "Running " << context.executable_name << "\n";
-
- const CPUInfo &info = context.cpu_info;
- Out << "Run on (" << info.num_cpus << " X "
- << (info.cycles_per_second / 1000000.0) << " MHz CPU "
- << ((info.num_cpus > 1) ? "s" : "") << ")\n";
- if (info.caches.size() != 0) {
- Out << "CPU Caches:\n";
- for (auto &CInfo : info.caches) {
- Out << " L" << CInfo.level << " " << CInfo.type << " "
- << (CInfo.size / 1024) << " KiB";
- if (CInfo.num_sharing != 0)
- Out << " (x" << (info.num_cpus / CInfo.num_sharing) << ")";
- Out << "\n";
- }
- }
- if (!info.load_avg.empty()) {
- Out << "Load Average: ";
- for (auto It = info.load_avg.begin(); It != info.load_avg.end();) {
- Out << StrFormat("%.2f", *It++);
- if (It != info.load_avg.end()) Out << ", ";
- }
- Out << "\n";
- }
-
- if (info.scaling_enabled) {
- Out << "***WARNING*** CPU scaling is enabled, the benchmark "
- "real time measurements may be noisy and will incur extra "
- "overhead.\n";
- }
-
-#ifndef NDEBUG
- Out << "***WARNING*** Library was built as DEBUG. Timings may be "
- "affected.\n";
-#endif
-}
-
-// No initializer because it's already initialized to NULL.
-const char *BenchmarkReporter::Context::executable_name;
-
-BenchmarkReporter::Context::Context()
- : cpu_info(CPUInfo::Get()), sys_info(SystemInfo::Get()) {}
-
-std::string BenchmarkReporter::Run::benchmark_name() const {
- std::string name = run_name.str();
- if (run_type == RT_Aggregate) {
- name += "_" + aggregate_name;
- }
- return name;
-}
-
-double BenchmarkReporter::Run::GetAdjustedRealTime() const {
- double new_time = real_accumulated_time * GetTimeUnitMultiplier(time_unit);
- if (iterations != 0) new_time /= static_cast<double>(iterations);
- return new_time;
-}
-
-double BenchmarkReporter::Run::GetAdjustedCPUTime() const {
- double new_time = cpu_accumulated_time * GetTimeUnitMultiplier(time_unit);
- if (iterations != 0) new_time /= static_cast<double>(iterations);
- return new_time;
-}
-
-} // end namespace benchmark
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "sleep.h"
-
-#include <cerrno>
-#include <cstdlib>
-#include <ctime>
-
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include <windows.h>
-#endif
-
-namespace benchmark {
-#ifdef BENCHMARK_OS_WINDOWS
-// Window's Sleep takes milliseconds argument.
-void SleepForMilliseconds(int milliseconds) { Sleep(milliseconds); }
-void SleepForSeconds(double seconds) {
- SleepForMilliseconds(static_cast<int>(kNumMillisPerSecond * seconds));
-}
-#else // BENCHMARK_OS_WINDOWS
-void SleepForMicroseconds(int microseconds) {
- struct timespec sleep_time;
- sleep_time.tv_sec = microseconds / kNumMicrosPerSecond;
- sleep_time.tv_nsec = (microseconds % kNumMicrosPerSecond) * kNumNanosPerMicro;
- while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR)
- ; // Ignore signals and wait for the full interval to elapse.
-}
-
-void SleepForMilliseconds(int milliseconds) {
- SleepForMicroseconds(milliseconds * kNumMicrosPerMilli);
-}
-
-void SleepForSeconds(double seconds) {
- SleepForMicroseconds(static_cast<int>(seconds * kNumMicrosPerSecond));
-}
-#endif // BENCHMARK_OS_WINDOWS
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_SLEEP_H_
-#define BENCHMARK_SLEEP_H_
-
-namespace benchmark {
-const int kNumMillisPerSecond = 1000;
-const int kNumMicrosPerMilli = 1000;
-const int kNumMicrosPerSecond = kNumMillisPerSecond * 1000;
-const int kNumNanosPerMicro = 1000;
-const int kNumNanosPerSecond = kNumNanosPerMicro * kNumMicrosPerSecond;
-
-void SleepForMilliseconds(int milliseconds);
-void SleepForSeconds(double seconds);
-} // end namespace benchmark
-
-#endif // BENCHMARK_SLEEP_H_
+++ /dev/null
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-// Copyright 2017 Roman Lebedev. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "benchmark/benchmark.h"
-
-#include <algorithm>
-#include <cmath>
-#include <numeric>
-#include <string>
-#include <vector>
-#include "check.h"
-#include "statistics.h"
-
-namespace benchmark {
-
-auto StatisticsSum = [](const std::vector<double>& v) {
- return std::accumulate(v.begin(), v.end(), 0.0);
-};
-
-double StatisticsMean(const std::vector<double>& v) {
- if (v.empty()) return 0.0;
- return StatisticsSum(v) * (1.0 / v.size());
-}
-
-double StatisticsMedian(const std::vector<double>& v) {
- if (v.size() < 3) return StatisticsMean(v);
- std::vector<double> copy(v);
-
- auto center = copy.begin() + v.size() / 2;
- std::nth_element(copy.begin(), center, copy.end());
-
- // did we have an odd number of samples?
- // if yes, then center is the median
- // it no, then we are looking for the average between center and the value
- // before
- if (v.size() % 2 == 1) return *center;
- auto center2 = copy.begin() + v.size() / 2 - 1;
- std::nth_element(copy.begin(), center2, copy.end());
- return (*center + *center2) / 2.0;
-}
-
-// Return the sum of the squares of this sample set
-auto SumSquares = [](const std::vector<double>& v) {
- return std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
-};
-
-auto Sqr = [](const double dat) { return dat * dat; };
-auto Sqrt = [](const double dat) {
- // Avoid NaN due to imprecision in the calculations
- if (dat < 0.0) return 0.0;
- return std::sqrt(dat);
-};
-
-double StatisticsStdDev(const std::vector<double>& v) {
- const auto mean = StatisticsMean(v);
- if (v.empty()) return mean;
-
- // Sample standard deviation is undefined for n = 1
- if (v.size() == 1) return 0.0;
-
- const double avg_squares = SumSquares(v) * (1.0 / v.size());
- return Sqrt(v.size() / (v.size() - 1.0) * (avg_squares - Sqr(mean)));
-}
-
-std::vector<BenchmarkReporter::Run> ComputeStats(
- const std::vector<BenchmarkReporter::Run>& reports) {
- typedef BenchmarkReporter::Run Run;
- std::vector<Run> results;
-
- auto error_count =
- std::count_if(reports.begin(), reports.end(),
- [](Run const& run) { return run.error_occurred; });
-
- if (reports.size() - error_count < 2) {
- // We don't report aggregated data if there was a single run.
- return results;
- }
-
- // Accumulators.
- std::vector<double> real_accumulated_time_stat;
- std::vector<double> cpu_accumulated_time_stat;
-
- real_accumulated_time_stat.reserve(reports.size());
- cpu_accumulated_time_stat.reserve(reports.size());
-
- // All repetitions should be run with the same number of iterations so we
- // can take this information from the first benchmark.
- const IterationCount run_iterations = reports.front().iterations;
- // create stats for user counters
- struct CounterStat {
- Counter c;
- std::vector<double> s;
- };
- std::map<std::string, CounterStat> counter_stats;
- for (Run const& r : reports) {
- for (auto const& cnt : r.counters) {
- auto it = counter_stats.find(cnt.first);
- if (it == counter_stats.end()) {
- counter_stats.insert({cnt.first, {cnt.second, std::vector<double>{}}});
- it = counter_stats.find(cnt.first);
- it->second.s.reserve(reports.size());
- } else {
- CHECK_EQ(counter_stats[cnt.first].c.flags, cnt.second.flags);
- }
- }
- }
-
- // Populate the accumulators.
- for (Run const& run : reports) {
- CHECK_EQ(reports[0].benchmark_name(), run.benchmark_name());
- CHECK_EQ(run_iterations, run.iterations);
- if (run.error_occurred) continue;
- real_accumulated_time_stat.emplace_back(run.real_accumulated_time);
- cpu_accumulated_time_stat.emplace_back(run.cpu_accumulated_time);
- // user counters
- for (auto const& cnt : run.counters) {
- auto it = counter_stats.find(cnt.first);
- CHECK_NE(it, counter_stats.end());
- it->second.s.emplace_back(cnt.second);
- }
- }
-
- // Only add label if it is same for all runs
- std::string report_label = reports[0].report_label;
- for (std::size_t i = 1; i < reports.size(); i++) {
- if (reports[i].report_label != report_label) {
- report_label = "";
- break;
- }
- }
-
- const double iteration_rescale_factor =
- double(reports.size()) / double(run_iterations);
-
- for (const auto& Stat : *reports[0].statistics) {
- // Get the data from the accumulator to BenchmarkReporter::Run's.
- Run data;
- data.run_name = reports[0].run_name;
- data.run_type = BenchmarkReporter::Run::RT_Aggregate;
- data.threads = reports[0].threads;
- data.repetitions = reports[0].repetitions;
- data.repetition_index = Run::no_repetition_index;
- data.aggregate_name = Stat.name_;
- data.report_label = report_label;
-
- // It is incorrect to say that an aggregate is computed over
- // run's iterations, because those iterations already got averaged.
- // Similarly, if there are N repetitions with 1 iterations each,
- // an aggregate will be computed over N measurements, not 1.
- // Thus it is best to simply use the count of separate reports.
- data.iterations = reports.size();
-
- data.real_accumulated_time = Stat.compute_(real_accumulated_time_stat);
- data.cpu_accumulated_time = Stat.compute_(cpu_accumulated_time_stat);
-
- // We will divide these times by data.iterations when reporting, but the
- // data.iterations is not nessesairly the scale of these measurements,
- // because in each repetition, these timers are sum over all the iterations.
- // And if we want to say that the stats are over N repetitions and not
- // M iterations, we need to multiply these by (N/M).
- data.real_accumulated_time *= iteration_rescale_factor;
- data.cpu_accumulated_time *= iteration_rescale_factor;
-
- data.time_unit = reports[0].time_unit;
-
- // user counters
- for (auto const& kv : counter_stats) {
- // Do *NOT* rescale the custom counters. They are already properly scaled.
- const auto uc_stat = Stat.compute_(kv.second.s);
- auto c = Counter(uc_stat, counter_stats[kv.first].c.flags,
- counter_stats[kv.first].c.oneK);
- data.counters[kv.first] = c;
- }
-
- results.push_back(data);
- }
-
- return results;
-}
-
-} // end namespace benchmark
+++ /dev/null
-// Copyright 2016 Ismael Jimenez Martinez. All rights reserved.
-// Copyright 2017 Roman Lebedev. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef STATISTICS_H_
-#define STATISTICS_H_
-
-#include <vector>
-
-#include "benchmark/benchmark.h"
-
-namespace benchmark {
-
-// Return a vector containing the mean, median and standard devation information
-// (and any user-specified info) for the specified list of reports. If 'reports'
-// contains less than two non-errored runs an empty vector is returned
-std::vector<BenchmarkReporter::Run> ComputeStats(
- const std::vector<BenchmarkReporter::Run>& reports);
-
-double StatisticsMean(const std::vector<double>& v);
-double StatisticsMedian(const std::vector<double>& v);
-double StatisticsStdDev(const std::vector<double>& v);
-
-} // end namespace benchmark
-
-#endif // STATISTICS_H_
+++ /dev/null
-#include "string_util.h"
-
-#include <array>
-#ifdef BENCHMARK_STL_ANDROID_GNUSTL
-#include <cerrno>
-#endif
-#include <cmath>
-#include <cstdarg>
-#include <cstdio>
-#include <memory>
-#include <sstream>
-
-#include "arraysize.h"
-
-namespace benchmark {
-namespace {
-
-// kilo, Mega, Giga, Tera, Peta, Exa, Zetta, Yotta.
-const char kBigSIUnits[] = "kMGTPEZY";
-// Kibi, Mebi, Gibi, Tebi, Pebi, Exbi, Zebi, Yobi.
-const char kBigIECUnits[] = "KMGTPEZY";
-// milli, micro, nano, pico, femto, atto, zepto, yocto.
-const char kSmallSIUnits[] = "munpfazy";
-
-// We require that all three arrays have the same size.
-static_assert(arraysize(kBigSIUnits) == arraysize(kBigIECUnits),
- "SI and IEC unit arrays must be the same size");
-static_assert(arraysize(kSmallSIUnits) == arraysize(kBigSIUnits),
- "Small SI and Big SI unit arrays must be the same size");
-
-static const int64_t kUnitsSize = arraysize(kBigSIUnits);
-
-void ToExponentAndMantissa(double val, double thresh, int precision,
- double one_k, std::string* mantissa,
- int64_t* exponent) {
- std::stringstream mantissa_stream;
-
- if (val < 0) {
- mantissa_stream << "-";
- val = -val;
- }
-
- // Adjust threshold so that it never excludes things which can't be rendered
- // in 'precision' digits.
- const double adjusted_threshold =
- std::max(thresh, 1.0 / std::pow(10.0, precision));
- const double big_threshold = adjusted_threshold * one_k;
- const double small_threshold = adjusted_threshold;
- // Values in ]simple_threshold,small_threshold[ will be printed as-is
- const double simple_threshold = 0.01;
-
- if (val > big_threshold) {
- // Positive powers
- double scaled = val;
- for (size_t i = 0; i < arraysize(kBigSIUnits); ++i) {
- scaled /= one_k;
- if (scaled <= big_threshold) {
- mantissa_stream << scaled;
- *exponent = i + 1;
- *mantissa = mantissa_stream.str();
- return;
- }
- }
- mantissa_stream << val;
- *exponent = 0;
- } else if (val < small_threshold) {
- // Negative powers
- if (val < simple_threshold) {
- double scaled = val;
- for (size_t i = 0; i < arraysize(kSmallSIUnits); ++i) {
- scaled *= one_k;
- if (scaled >= small_threshold) {
- mantissa_stream << scaled;
- *exponent = -static_cast<int64_t>(i + 1);
- *mantissa = mantissa_stream.str();
- return;
- }
- }
- }
- mantissa_stream << val;
- *exponent = 0;
- } else {
- mantissa_stream << val;
- *exponent = 0;
- }
- *mantissa = mantissa_stream.str();
-}
-
-std::string ExponentToPrefix(int64_t exponent, bool iec) {
- if (exponent == 0) return "";
-
- const int64_t index = (exponent > 0 ? exponent - 1 : -exponent - 1);
- if (index >= kUnitsSize) return "";
-
- const char* array =
- (exponent > 0 ? (iec ? kBigIECUnits : kBigSIUnits) : kSmallSIUnits);
- if (iec)
- return array[index] + std::string("i");
- else
- return std::string(1, array[index]);
-}
-
-std::string ToBinaryStringFullySpecified(double value, double threshold,
- int precision, double one_k = 1024.0) {
- std::string mantissa;
- int64_t exponent;
- ToExponentAndMantissa(value, threshold, precision, one_k, &mantissa,
- &exponent);
- return mantissa + ExponentToPrefix(exponent, false);
-}
-
-} // end namespace
-
-void AppendHumanReadable(int n, std::string* str) {
- std::stringstream ss;
- // Round down to the nearest SI prefix.
- ss << ToBinaryStringFullySpecified(n, 1.0, 0);
- *str += ss.str();
-}
-
-std::string HumanReadableNumber(double n, double one_k) {
- // 1.1 means that figures up to 1.1k should be shown with the next unit down;
- // this softens edge effects.
- // 1 means that we should show one decimal place of precision.
- return ToBinaryStringFullySpecified(n, 1.1, 1, one_k);
-}
-
-std::string StrFormatImp(const char* msg, va_list args) {
- // we might need a second shot at this, so pre-emptivly make a copy
- va_list args_cp;
- va_copy(args_cp, args);
-
- // TODO(ericwf): use std::array for first attempt to avoid one memory
- // allocation guess what the size might be
- std::array<char, 256> local_buff;
- std::size_t size = local_buff.size();
- // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
- // in the android-ndk
- auto ret = vsnprintf(local_buff.data(), size, msg, args_cp);
-
- va_end(args_cp);
-
- // handle empty expansion
- if (ret == 0) return std::string{};
- if (static_cast<std::size_t>(ret) < size)
- return std::string(local_buff.data());
-
- // we did not provide a long enough buffer on our first attempt.
- // add 1 to size to account for null-byte in size cast to prevent overflow
- size = static_cast<std::size_t>(ret) + 1;
- auto buff_ptr = std::unique_ptr<char[]>(new char[size]);
- // 2015-10-08: vsnprintf is used instead of snd::vsnprintf due to a limitation
- // in the android-ndk
- ret = vsnprintf(buff_ptr.get(), size, msg, args);
- return std::string(buff_ptr.get());
-}
-
-std::string StrFormat(const char* format, ...) {
- va_list args;
- va_start(args, format);
- std::string tmp = StrFormatImp(format, args);
- va_end(args);
- return tmp;
-}
-
-#ifdef BENCHMARK_STL_ANDROID_GNUSTL
-/*
- * GNU STL in Android NDK lacks support for some C++11 functions, including
- * stoul, stoi, stod. We reimplement them here using C functions strtoul,
- * strtol, strtod. Note that reimplemented functions are in benchmark::
- * namespace, not std:: namespace.
- */
-unsigned long stoul(const std::string& str, size_t* pos, int base) {
- /* Record previous errno */
- const int oldErrno = errno;
- errno = 0;
-
- const char* strStart = str.c_str();
- char* strEnd = const_cast<char*>(strStart);
- const unsigned long result = strtoul(strStart, &strEnd, base);
-
- const int strtoulErrno = errno;
- /* Restore previous errno */
- errno = oldErrno;
-
- /* Check for errors and return */
- if (strtoulErrno == ERANGE) {
- throw std::out_of_range(
- "stoul failed: " + str + " is outside of range of unsigned long");
- } else if (strEnd == strStart || strtoulErrno != 0) {
- throw std::invalid_argument(
- "stoul failed: " + str + " is not an integer");
- }
- if (pos != nullptr) {
- *pos = static_cast<size_t>(strEnd - strStart);
- }
- return result;
-}
-
-int stoi(const std::string& str, size_t* pos, int base) {
- /* Record previous errno */
- const int oldErrno = errno;
- errno = 0;
-
- const char* strStart = str.c_str();
- char* strEnd = const_cast<char*>(strStart);
- const long result = strtol(strStart, &strEnd, base);
-
- const int strtolErrno = errno;
- /* Restore previous errno */
- errno = oldErrno;
-
- /* Check for errors and return */
- if (strtolErrno == ERANGE || long(int(result)) != result) {
- throw std::out_of_range(
- "stoul failed: " + str + " is outside of range of int");
- } else if (strEnd == strStart || strtolErrno != 0) {
- throw std::invalid_argument(
- "stoul failed: " + str + " is not an integer");
- }
- if (pos != nullptr) {
- *pos = static_cast<size_t>(strEnd - strStart);
- }
- return int(result);
-}
-
-double stod(const std::string& str, size_t* pos) {
- /* Record previous errno */
- const int oldErrno = errno;
- errno = 0;
-
- const char* strStart = str.c_str();
- char* strEnd = const_cast<char*>(strStart);
- const double result = strtod(strStart, &strEnd);
-
- /* Restore previous errno */
- const int strtodErrno = errno;
- errno = oldErrno;
-
- /* Check for errors and return */
- if (strtodErrno == ERANGE) {
- throw std::out_of_range(
- "stoul failed: " + str + " is outside of range of int");
- } else if (strEnd == strStart || strtodErrno != 0) {
- throw std::invalid_argument(
- "stoul failed: " + str + " is not an integer");
- }
- if (pos != nullptr) {
- *pos = static_cast<size_t>(strEnd - strStart);
- }
- return result;
-}
-#endif
-
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_STRING_UTIL_H_
-#define BENCHMARK_STRING_UTIL_H_
-
-#include <sstream>
-#include <string>
-#include <utility>
-#include "internal_macros.h"
-
-namespace benchmark {
-
-void AppendHumanReadable(int n, std::string* str);
-
-std::string HumanReadableNumber(double n, double one_k = 1024.0);
-
-#if defined(__MINGW32__)
-__attribute__((format(__MINGW_PRINTF_FORMAT, 1, 2)))
-#elif defined(__GNUC__)
-__attribute__((format(printf, 1, 2)))
-#endif
-std::string
-StrFormat(const char* format, ...);
-
-inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT {
- return out;
-}
-
-template <class First, class... Rest>
-inline std::ostream& StrCatImp(std::ostream& out, First&& f, Rest&&... rest) {
- out << std::forward<First>(f);
- return StrCatImp(out, std::forward<Rest>(rest)...);
-}
-
-template <class... Args>
-inline std::string StrCat(Args&&... args) {
- std::ostringstream ss;
- StrCatImp(ss, std::forward<Args>(args)...);
- return ss.str();
-}
-
-#ifdef BENCHMARK_STL_ANDROID_GNUSTL
-/*
- * GNU STL in Android NDK lacks support for some C++11 functions, including
- * stoul, stoi, stod. We reimplement them here using C functions strtoul,
- * strtol, strtod. Note that reimplemented functions are in benchmark::
- * namespace, not std:: namespace.
- */
-unsigned long stoul(const std::string& str, size_t* pos = nullptr,
- int base = 10);
-int stoi(const std::string& str, size_t* pos = nullptr, int base = 10);
-double stod(const std::string& str, size_t* pos = nullptr);
-#else
-using std::stoul;
-using std::stoi;
-using std::stod;
-#endif
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_STRING_UTIL_H_
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include <shlwapi.h>
-#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
-#include <versionhelpers.h>
-#include <windows.h>
-#include <codecvt>
-#else
-#include <fcntl.h>
-#ifndef BENCHMARK_OS_FUCHSIA
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
-#include <unistd.h>
-#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \
- defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD
-#define BENCHMARK_HAS_SYSCTL
-#include <sys/sysctl.h>
-#endif
-#endif
-#if defined(BENCHMARK_OS_SOLARIS)
-#include <kstat.h>
-#endif
-#if defined(BENCHMARK_OS_QNX)
-#include <sys/syspage.h>
-#endif
-
-#include <algorithm>
-#include <array>
-#include <bitset>
-#include <cerrno>
-#include <climits>
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <iterator>
-#include <limits>
-#include <memory>
-#include <sstream>
-#include <locale>
-
-#include "check.h"
-#include "cycleclock.h"
-#include "internal_macros.h"
-#include "log.h"
-#include "sleep.h"
-#include "string_util.h"
-
-namespace benchmark {
-namespace {
-
-void PrintImp(std::ostream& out) { out << std::endl; }
-
-template <class First, class... Rest>
-void PrintImp(std::ostream& out, First&& f, Rest&&... rest) {
- out << std::forward<First>(f);
- PrintImp(out, std::forward<Rest>(rest)...);
-}
-
-template <class... Args>
-BENCHMARK_NORETURN void PrintErrorAndDie(Args&&... args) {
- PrintImp(std::cerr, std::forward<Args>(args)...);
- std::exit(EXIT_FAILURE);
-}
-
-#ifdef BENCHMARK_HAS_SYSCTL
-
-/// ValueUnion - A type used to correctly alias the byte-for-byte output of
-/// `sysctl` with the result type it's to be interpreted as.
-struct ValueUnion {
- union DataT {
- uint32_t uint32_value;
- uint64_t uint64_value;
- // For correct aliasing of union members from bytes.
- char bytes[8];
- };
- using DataPtr = std::unique_ptr<DataT, decltype(&std::free)>;
-
- // The size of the data union member + its trailing array size.
- size_t Size;
- DataPtr Buff;
-
- public:
- ValueUnion() : Size(0), Buff(nullptr, &std::free) {}
-
- explicit ValueUnion(size_t BuffSize)
- : Size(sizeof(DataT) + BuffSize),
- Buff(::new (std::malloc(Size)) DataT(), &std::free) {}
-
- ValueUnion(ValueUnion&& other) = default;
-
- explicit operator bool() const { return bool(Buff); }
-
- char* data() const { return Buff->bytes; }
-
- std::string GetAsString() const { return std::string(data()); }
-
- int64_t GetAsInteger() const {
- if (Size == sizeof(Buff->uint32_value))
- return static_cast<int32_t>(Buff->uint32_value);
- else if (Size == sizeof(Buff->uint64_value))
- return static_cast<int64_t>(Buff->uint64_value);
- BENCHMARK_UNREACHABLE();
- }
-
- uint64_t GetAsUnsigned() const {
- if (Size == sizeof(Buff->uint32_value))
- return Buff->uint32_value;
- else if (Size == sizeof(Buff->uint64_value))
- return Buff->uint64_value;
- BENCHMARK_UNREACHABLE();
- }
-
- template <class T, int N>
- std::array<T, N> GetAsArray() {
- const int ArrSize = sizeof(T) * N;
- CHECK_LE(ArrSize, Size);
- std::array<T, N> Arr;
- std::memcpy(Arr.data(), data(), ArrSize);
- return Arr;
- }
-};
-
-ValueUnion GetSysctlImp(std::string const& Name) {
-#if defined BENCHMARK_OS_OPENBSD
- int mib[2];
-
- mib[0] = CTL_HW;
- if ((Name == "hw.ncpu") || (Name == "hw.cpuspeed")){
- ValueUnion buff(sizeof(int));
-
- if (Name == "hw.ncpu") {
- mib[1] = HW_NCPU;
- } else {
- mib[1] = HW_CPUSPEED;
- }
-
- if (sysctl(mib, 2, buff.data(), &buff.Size, nullptr, 0) == -1) {
- return ValueUnion();
- }
- return buff;
- }
- return ValueUnion();
-#else
- size_t CurBuffSize = 0;
- if (sysctlbyname(Name.c_str(), nullptr, &CurBuffSize, nullptr, 0) == -1)
- return ValueUnion();
-
- ValueUnion buff(CurBuffSize);
- if (sysctlbyname(Name.c_str(), buff.data(), &buff.Size, nullptr, 0) == 0)
- return buff;
- return ValueUnion();
-#endif
-}
-
-BENCHMARK_MAYBE_UNUSED
-bool GetSysctl(std::string const& Name, std::string* Out) {
- Out->clear();
- auto Buff = GetSysctlImp(Name);
- if (!Buff) return false;
- Out->assign(Buff.data());
- return true;
-}
-
-template <class Tp,
- class = typename std::enable_if<std::is_integral<Tp>::value>::type>
-bool GetSysctl(std::string const& Name, Tp* Out) {
- *Out = 0;
- auto Buff = GetSysctlImp(Name);
- if (!Buff) return false;
- *Out = static_cast<Tp>(Buff.GetAsUnsigned());
- return true;
-}
-
-template <class Tp, size_t N>
-bool GetSysctl(std::string const& Name, std::array<Tp, N>* Out) {
- auto Buff = GetSysctlImp(Name);
- if (!Buff) return false;
- *Out = Buff.GetAsArray<Tp, N>();
- return true;
-}
-#endif
-
-template <class ArgT>
-bool ReadFromFile(std::string const& fname, ArgT* arg) {
- *arg = ArgT();
- std::ifstream f(fname.c_str());
- if (!f.is_open()) return false;
- f >> *arg;
- return f.good();
-}
-
-bool CpuScalingEnabled(int num_cpus) {
- // We don't have a valid CPU count, so don't even bother.
- if (num_cpus <= 0) return false;
-#ifdef BENCHMARK_OS_QNX
- return false;
-#endif
-#ifndef BENCHMARK_OS_WINDOWS
- // On Linux, the CPUfreq subsystem exposes CPU information as files on the
- // local file system. If reading the exported files fails, then we may not be
- // running on Linux, so we silently ignore all the read errors.
- std::string res;
- for (int cpu = 0; cpu < num_cpus; ++cpu) {
- std::string governor_file =
- StrCat("/sys/devices/system/cpu/cpu", cpu, "/cpufreq/scaling_governor");
- if (ReadFromFile(governor_file, &res) && res != "performance") return true;
- }
-#endif
- return false;
-}
-
-int CountSetBitsInCPUMap(std::string Val) {
- auto CountBits = [](std::string Part) {
- using CPUMask = std::bitset<sizeof(std::uintptr_t) * CHAR_BIT>;
- Part = "0x" + Part;
- CPUMask Mask(benchmark::stoul(Part, nullptr, 16));
- return static_cast<int>(Mask.count());
- };
- size_t Pos;
- int total = 0;
- while ((Pos = Val.find(',')) != std::string::npos) {
- total += CountBits(Val.substr(0, Pos));
- Val = Val.substr(Pos + 1);
- }
- if (!Val.empty()) {
- total += CountBits(Val);
- }
- return total;
-}
-
-BENCHMARK_MAYBE_UNUSED
-std::vector<CPUInfo::CacheInfo> GetCacheSizesFromKVFS() {
- std::vector<CPUInfo::CacheInfo> res;
- std::string dir = "/sys/devices/system/cpu/cpu0/cache/";
- int Idx = 0;
- while (true) {
- CPUInfo::CacheInfo info;
- std::string FPath = StrCat(dir, "index", Idx++, "/");
- std::ifstream f(StrCat(FPath, "size").c_str());
- if (!f.is_open()) break;
- std::string suffix;
- f >> info.size;
- if (f.fail())
- PrintErrorAndDie("Failed while reading file '", FPath, "size'");
- if (f.good()) {
- f >> suffix;
- if (f.bad())
- PrintErrorAndDie(
- "Invalid cache size format: failed to read size suffix");
- else if (f && suffix != "K")
- PrintErrorAndDie("Invalid cache size format: Expected bytes ", suffix);
- else if (suffix == "K")
- info.size *= 1024;
- }
- if (!ReadFromFile(StrCat(FPath, "type"), &info.type))
- PrintErrorAndDie("Failed to read from file ", FPath, "type");
- if (!ReadFromFile(StrCat(FPath, "level"), &info.level))
- PrintErrorAndDie("Failed to read from file ", FPath, "level");
- std::string map_str;
- if (!ReadFromFile(StrCat(FPath, "shared_cpu_map"), &map_str))
- PrintErrorAndDie("Failed to read from file ", FPath, "shared_cpu_map");
- info.num_sharing = CountSetBitsInCPUMap(map_str);
- res.push_back(info);
- }
-
- return res;
-}
-
-#ifdef BENCHMARK_OS_MACOSX
-std::vector<CPUInfo::CacheInfo> GetCacheSizesMacOSX() {
- std::vector<CPUInfo::CacheInfo> res;
- std::array<uint64_t, 4> CacheCounts{{0, 0, 0, 0}};
- GetSysctl("hw.cacheconfig", &CacheCounts);
-
- struct {
- std::string name;
- std::string type;
- int level;
- uint64_t num_sharing;
- } Cases[] = {{"hw.l1dcachesize", "Data", 1, CacheCounts[1]},
- {"hw.l1icachesize", "Instruction", 1, CacheCounts[1]},
- {"hw.l2cachesize", "Unified", 2, CacheCounts[2]},
- {"hw.l3cachesize", "Unified", 3, CacheCounts[3]}};
- for (auto& C : Cases) {
- int val;
- if (!GetSysctl(C.name, &val)) continue;
- CPUInfo::CacheInfo info;
- info.type = C.type;
- info.level = C.level;
- info.size = val;
- info.num_sharing = static_cast<int>(C.num_sharing);
- res.push_back(std::move(info));
- }
- return res;
-}
-#elif defined(BENCHMARK_OS_WINDOWS)
-std::vector<CPUInfo::CacheInfo> GetCacheSizesWindows() {
- std::vector<CPUInfo::CacheInfo> res;
- DWORD buffer_size = 0;
- using PInfo = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
- using CInfo = CACHE_DESCRIPTOR;
-
- using UPtr = std::unique_ptr<PInfo, decltype(&std::free)>;
- GetLogicalProcessorInformation(nullptr, &buffer_size);
- UPtr buff((PInfo*)malloc(buffer_size), &std::free);
- if (!GetLogicalProcessorInformation(buff.get(), &buffer_size))
- PrintErrorAndDie("Failed during call to GetLogicalProcessorInformation: ",
- GetLastError());
-
- PInfo* it = buff.get();
- PInfo* end = buff.get() + (buffer_size / sizeof(PInfo));
-
- for (; it != end; ++it) {
- if (it->Relationship != RelationCache) continue;
- using BitSet = std::bitset<sizeof(ULONG_PTR) * CHAR_BIT>;
- BitSet B(it->ProcessorMask);
- // To prevent duplicates, only consider caches where CPU 0 is specified
- if (!B.test(0)) continue;
- CInfo* Cache = &it->Cache;
- CPUInfo::CacheInfo C;
- C.num_sharing = static_cast<int>(B.count());
- C.level = Cache->Level;
- C.size = Cache->Size;
- switch (Cache->Type) {
- case CacheUnified:
- C.type = "Unified";
- break;
- case CacheInstruction:
- C.type = "Instruction";
- break;
- case CacheData:
- C.type = "Data";
- break;
- case CacheTrace:
- C.type = "Trace";
- break;
- default:
- C.type = "Unknown";
- break;
- }
- res.push_back(C);
- }
- return res;
-}
-#elif BENCHMARK_OS_QNX
-std::vector<CPUInfo::CacheInfo> GetCacheSizesQNX() {
- std::vector<CPUInfo::CacheInfo> res;
- struct cacheattr_entry *cache = SYSPAGE_ENTRY(cacheattr);
- uint32_t const elsize = SYSPAGE_ELEMENT_SIZE(cacheattr);
- int num = SYSPAGE_ENTRY_SIZE(cacheattr) / elsize ;
- for(int i = 0; i < num; ++i ) {
- CPUInfo::CacheInfo info;
- switch (cache->flags){
- case CACHE_FLAG_INSTR :
- info.type = "Instruction";
- info.level = 1;
- break;
- case CACHE_FLAG_DATA :
- info.type = "Data";
- info.level = 1;
- break;
- case CACHE_FLAG_UNIFIED :
- info.type = "Unified";
- info.level = 2;
- case CACHE_FLAG_SHARED :
- info.type = "Shared";
- info.level = 3;
- default :
- continue;
- break;
- }
- info.size = cache->line_size * cache->num_lines;
- info.num_sharing = 0;
- res.push_back(std::move(info));
- cache = SYSPAGE_ARRAY_ADJ_OFFSET(cacheattr, cache, elsize);
- }
- return res;
-}
-#endif
-
-std::vector<CPUInfo::CacheInfo> GetCacheSizes() {
-#ifdef BENCHMARK_OS_MACOSX
- return GetCacheSizesMacOSX();
-#elif defined(BENCHMARK_OS_WINDOWS)
- return GetCacheSizesWindows();
-#elif defined(BENCHMARK_OS_QNX)
- return GetCacheSizesQNX();
-#else
- return GetCacheSizesFromKVFS();
-#endif
-}
-
-std::string GetSystemName() {
-#if defined(BENCHMARK_OS_WINDOWS)
- std::string str;
- const unsigned COUNT = MAX_COMPUTERNAME_LENGTH+1;
- TCHAR hostname[COUNT] = {'\0'};
- DWORD DWCOUNT = COUNT;
- if (!GetComputerName(hostname, &DWCOUNT))
- return std::string("");
-#ifndef UNICODE
- str = std::string(hostname, DWCOUNT);
-#else
- //Using wstring_convert, Is deprecated in C++17
- using convert_type = std::codecvt_utf8<wchar_t>;
- std::wstring_convert<convert_type, wchar_t> converter;
- std::wstring wStr(hostname, DWCOUNT);
- str = converter.to_bytes(wStr);
-#endif
- return str;
-#else // defined(BENCHMARK_OS_WINDOWS)
-#ifndef HOST_NAME_MAX
-#ifdef BENCHMARK_HAS_SYSCTL // BSD/Mac Doesnt have HOST_NAME_MAX defined
-#define HOST_NAME_MAX 64
-#elif defined(BENCHMARK_OS_NACL)
-#define HOST_NAME_MAX 64
-#elif defined(BENCHMARK_OS_QNX)
-#define HOST_NAME_MAX 154
-#elif defined(BENCHMARK_OS_RTEMS)
-#define HOST_NAME_MAX 256
-#else
-#warning "HOST_NAME_MAX not defined. using 64"
-#define HOST_NAME_MAX 64
-#endif
-#endif // def HOST_NAME_MAX
- char hostname[HOST_NAME_MAX];
- int retVal = gethostname(hostname, HOST_NAME_MAX);
- if (retVal != 0) return std::string("");
- return std::string(hostname);
-#endif // Catch-all POSIX block.
-}
-
-int GetNumCPUs() {
-#ifdef BENCHMARK_HAS_SYSCTL
- int NumCPU = -1;
- if (GetSysctl("hw.ncpu", &NumCPU)) return NumCPU;
- fprintf(stderr, "Err: %s\n", strerror(errno));
- std::exit(EXIT_FAILURE);
-#elif defined(BENCHMARK_OS_WINDOWS)
- SYSTEM_INFO sysinfo;
- // Use memset as opposed to = {} to avoid GCC missing initializer false
- // positives.
- std::memset(&sysinfo, 0, sizeof(SYSTEM_INFO));
- GetSystemInfo(&sysinfo);
- return sysinfo.dwNumberOfProcessors; // number of logical
- // processors in the current
- // group
-#elif defined(BENCHMARK_OS_SOLARIS)
- // Returns -1 in case of a failure.
- int NumCPU = sysconf(_SC_NPROCESSORS_ONLN);
- if (NumCPU < 0) {
- fprintf(stderr,
- "sysconf(_SC_NPROCESSORS_ONLN) failed with error: %s\n",
- strerror(errno));
- }
- return NumCPU;
-#elif defined(BENCHMARK_OS_QNX)
- return static_cast<int>(_syspage_ptr->num_cpu);
-#else
- int NumCPUs = 0;
- int MaxID = -1;
- std::ifstream f("/proc/cpuinfo");
- if (!f.is_open()) {
- std::cerr << "failed to open /proc/cpuinfo\n";
- return -1;
- }
- const std::string Key = "processor";
- std::string ln;
- while (std::getline(f, ln)) {
- if (ln.empty()) continue;
- size_t SplitIdx = ln.find(':');
- std::string value;
-#if defined(__s390__)
- // s390 has another format in /proc/cpuinfo
- // it needs to be parsed differently
- if (SplitIdx != std::string::npos) value = ln.substr(Key.size()+1,SplitIdx-Key.size()-1);
-#else
- if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1);
-#endif
- if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) {
- NumCPUs++;
- if (!value.empty()) {
- int CurID = benchmark::stoi(value);
- MaxID = std::max(CurID, MaxID);
- }
- }
- }
- if (f.bad()) {
- std::cerr << "Failure reading /proc/cpuinfo\n";
- return -1;
- }
- if (!f.eof()) {
- std::cerr << "Failed to read to end of /proc/cpuinfo\n";
- return -1;
- }
- f.close();
-
- if ((MaxID + 1) != NumCPUs) {
- fprintf(stderr,
- "CPU ID assignments in /proc/cpuinfo seem messed up."
- " This is usually caused by a bad BIOS.\n");
- }
- return NumCPUs;
-#endif
- BENCHMARK_UNREACHABLE();
-}
-
-double GetCPUCyclesPerSecond() {
-#if defined BENCHMARK_OS_LINUX || defined BENCHMARK_OS_CYGWIN
- long freq;
-
- // If the kernel is exporting the tsc frequency use that. There are issues
- // where cpuinfo_max_freq cannot be relied on because the BIOS may be
- // exporintg an invalid p-state (on x86) or p-states may be used to put the
- // processor in a new mode (turbo mode). Essentially, those frequencies
- // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
- // well.
- if (ReadFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)
- // If CPU scaling is in effect, we want to use the *maximum* frequency,
- // not whatever CPU speed some random processor happens to be using now.
- || ReadFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
- &freq)) {
- // The value is in kHz (as the file name suggests). For example, on a
- // 2GHz warpstation, the file contains the value "2000000".
- return freq * 1000.0;
- }
-
- const double error_value = -1;
- double bogo_clock = error_value;
-
- std::ifstream f("/proc/cpuinfo");
- if (!f.is_open()) {
- std::cerr << "failed to open /proc/cpuinfo\n";
- return error_value;
- }
-
- auto startsWithKey = [](std::string const& Value, std::string const& Key) {
- if (Key.size() > Value.size()) return false;
- auto Cmp = [&](char X, char Y) {
- return std::tolower(X) == std::tolower(Y);
- };
- return std::equal(Key.begin(), Key.end(), Value.begin(), Cmp);
- };
-
- std::string ln;
- while (std::getline(f, ln)) {
- if (ln.empty()) continue;
- size_t SplitIdx = ln.find(':');
- std::string value;
- if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1);
- // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
- // accept positive values. Some environments (virtual machines) report zero,
- // which would cause infinite looping in WallTime_Init.
- if (startsWithKey(ln, "cpu MHz")) {
- if (!value.empty()) {
- double cycles_per_second = benchmark::stod(value) * 1000000.0;
- if (cycles_per_second > 0) return cycles_per_second;
- }
- } else if (startsWithKey(ln, "bogomips")) {
- if (!value.empty()) {
- bogo_clock = benchmark::stod(value) * 1000000.0;
- if (bogo_clock < 0.0) bogo_clock = error_value;
- }
- }
- }
- if (f.bad()) {
- std::cerr << "Failure reading /proc/cpuinfo\n";
- return error_value;
- }
- if (!f.eof()) {
- std::cerr << "Failed to read to end of /proc/cpuinfo\n";
- return error_value;
- }
- f.close();
- // If we found the bogomips clock, but nothing better, we'll use it (but
- // we're not happy about it); otherwise, fallback to the rough estimation
- // below.
- if (bogo_clock >= 0.0) return bogo_clock;
-
-#elif defined BENCHMARK_HAS_SYSCTL
- constexpr auto* FreqStr =
-#if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD)
- "machdep.tsc_freq";
-#elif defined BENCHMARK_OS_OPENBSD
- "hw.cpuspeed";
-#else
- "hw.cpufrequency";
-#endif
- unsigned long long hz = 0;
-#if defined BENCHMARK_OS_OPENBSD
- if (GetSysctl(FreqStr, &hz)) return hz * 1000000;
-#else
- if (GetSysctl(FreqStr, &hz)) return hz;
-#endif
- fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n",
- FreqStr, strerror(errno));
-
-#elif defined BENCHMARK_OS_WINDOWS
- // In NT, read MHz from the registry. If we fail to do so or we're in win9x
- // then make a crude estimate.
- DWORD data, data_size = sizeof(data);
- if (IsWindowsXPOrGreater() &&
- SUCCEEDED(
- SHGetValueA(HKEY_LOCAL_MACHINE,
- "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
- "~MHz", nullptr, &data, &data_size)))
- return static_cast<double>((int64_t)data *
- (int64_t)(1000 * 1000)); // was mhz
-#elif defined (BENCHMARK_OS_SOLARIS)
- kstat_ctl_t *kc = kstat_open();
- if (!kc) {
- std::cerr << "failed to open /dev/kstat\n";
- return -1;
- }
- kstat_t *ksp = kstat_lookup(kc, (char*)"cpu_info", -1, (char*)"cpu_info0");
- if (!ksp) {
- std::cerr << "failed to lookup in /dev/kstat\n";
- return -1;
- }
- if (kstat_read(kc, ksp, NULL) < 0) {
- std::cerr << "failed to read from /dev/kstat\n";
- return -1;
- }
- kstat_named_t *knp =
- (kstat_named_t*)kstat_data_lookup(ksp, (char*)"current_clock_Hz");
- if (!knp) {
- std::cerr << "failed to lookup data in /dev/kstat\n";
- return -1;
- }
- if (knp->data_type != KSTAT_DATA_UINT64) {
- std::cerr << "current_clock_Hz is of unexpected data type: "
- << knp->data_type << "\n";
- return -1;
- }
- double clock_hz = knp->value.ui64;
- kstat_close(kc);
- return clock_hz;
-#elif defined (BENCHMARK_OS_QNX)
- return static_cast<double>((int64_t)(SYSPAGE_ENTRY(cpuinfo)->speed) *
- (int64_t)(1000 * 1000));
-#endif
- // If we've fallen through, attempt to roughly estimate the CPU clock rate.
- const int estimate_time_ms = 1000;
- const auto start_ticks = cycleclock::Now();
- SleepForMilliseconds(estimate_time_ms);
- return static_cast<double>(cycleclock::Now() - start_ticks);
-}
-
-std::vector<double> GetLoadAvg() {
-#if (defined BENCHMARK_OS_FREEBSD || defined(BENCHMARK_OS_LINUX) || \
- defined BENCHMARK_OS_MACOSX || defined BENCHMARK_OS_NETBSD || \
- defined BENCHMARK_OS_OPENBSD) && !defined(__ANDROID__)
- constexpr int kMaxSamples = 3;
- std::vector<double> res(kMaxSamples, 0.0);
- const int nelem = getloadavg(res.data(), kMaxSamples);
- if (nelem < 1) {
- res.clear();
- } else {
- res.resize(nelem);
- }
- return res;
-#else
- return {};
-#endif
-}
-
-} // end namespace
-
-const CPUInfo& CPUInfo::Get() {
- static const CPUInfo* info = new CPUInfo();
- return *info;
-}
-
-CPUInfo::CPUInfo()
- : num_cpus(GetNumCPUs()),
- cycles_per_second(GetCPUCyclesPerSecond()),
- caches(GetCacheSizes()),
- scaling_enabled(CpuScalingEnabled(num_cpus)),
- load_avg(GetLoadAvg()) {}
-
-
-const SystemInfo& SystemInfo::Get() {
- static const SystemInfo* info = new SystemInfo();
- return *info;
-}
-
-SystemInfo::SystemInfo() : name(GetSystemName()) {}
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_THREAD_MANAGER_H
-#define BENCHMARK_THREAD_MANAGER_H
-
-#include <atomic>
-
-#include "benchmark/benchmark.h"
-#include "mutex.h"
-
-namespace benchmark {
-namespace internal {
-
-class ThreadManager {
- public:
- explicit ThreadManager(int num_threads)
- : alive_threads_(num_threads), start_stop_barrier_(num_threads) {}
-
- Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) {
- return benchmark_mutex_;
- }
-
- bool StartStopBarrier() EXCLUDES(end_cond_mutex_) {
- return start_stop_barrier_.wait();
- }
-
- void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) {
- start_stop_barrier_.removeThread();
- if (--alive_threads_ == 0) {
- MutexLock lock(end_cond_mutex_);
- end_condition_.notify_all();
- }
- }
-
- void WaitForAllThreads() EXCLUDES(end_cond_mutex_) {
- MutexLock lock(end_cond_mutex_);
- end_condition_.wait(lock.native_handle(),
- [this]() { return alive_threads_ == 0; });
- }
-
- public:
- struct Result {
- IterationCount iterations = 0;
- double real_time_used = 0;
- double cpu_time_used = 0;
- double manual_time_used = 0;
- int64_t complexity_n = 0;
- std::string report_label_;
- std::string error_message_;
- bool has_error_ = false;
- UserCounters counters;
- };
- GUARDED_BY(GetBenchmarkMutex()) Result results;
-
- private:
- mutable Mutex benchmark_mutex_;
- std::atomic<int> alive_threads_;
- Barrier start_stop_barrier_;
- Mutex end_cond_mutex_;
- Condition end_condition_;
-};
-
-} // namespace internal
-} // namespace benchmark
-
-#endif // BENCHMARK_THREAD_MANAGER_H
+++ /dev/null
-#ifndef BENCHMARK_THREAD_TIMER_H
-#define BENCHMARK_THREAD_TIMER_H
-
-#include "check.h"
-#include "timers.h"
-
-namespace benchmark {
-namespace internal {
-
-class ThreadTimer {
- explicit ThreadTimer(bool measure_process_cpu_time_)
- : measure_process_cpu_time(measure_process_cpu_time_) {}
-
- public:
- static ThreadTimer Create() {
- return ThreadTimer(/*measure_process_cpu_time_=*/false);
- }
- static ThreadTimer CreateProcessCpuTime() {
- return ThreadTimer(/*measure_process_cpu_time_=*/true);
- }
-
- // Called by each thread
- void StartTimer() {
- running_ = true;
- start_real_time_ = ChronoClockNow();
- start_cpu_time_ = ReadCpuTimerOfChoice();
- }
-
- // Called by each thread
- void StopTimer() {
- CHECK(running_);
- running_ = false;
- real_time_used_ += ChronoClockNow() - start_real_time_;
- // Floating point error can result in the subtraction producing a negative
- // time. Guard against that.
- cpu_time_used_ +=
- std::max<double>(ReadCpuTimerOfChoice() - start_cpu_time_, 0);
- }
-
- // Called by each thread
- void SetIterationTime(double seconds) { manual_time_used_ += seconds; }
-
- bool running() const { return running_; }
-
- // REQUIRES: timer is not running
- double real_time_used() const {
- CHECK(!running_);
- return real_time_used_;
- }
-
- // REQUIRES: timer is not running
- double cpu_time_used() const {
- CHECK(!running_);
- return cpu_time_used_;
- }
-
- // REQUIRES: timer is not running
- double manual_time_used() const {
- CHECK(!running_);
- return manual_time_used_;
- }
-
- private:
- double ReadCpuTimerOfChoice() const {
- if (measure_process_cpu_time) return ProcessCPUUsage();
- return ThreadCPUUsage();
- }
-
- // should the thread, or the process, time be measured?
- const bool measure_process_cpu_time;
-
- bool running_ = false; // Is the timer running
- double start_real_time_ = 0; // If running_
- double start_cpu_time_ = 0; // If running_
-
- // Accumulated time so far (does not contain current slice if running_)
- double real_time_used_ = 0;
- double cpu_time_used_ = 0;
- // Manually set iteration time. User sets this with SetIterationTime(seconds).
- double manual_time_used_ = 0;
-};
-
-} // namespace internal
-} // namespace benchmark
-
-#endif // BENCHMARK_THREAD_TIMER_H
+++ /dev/null
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "timers.h"
-#include "internal_macros.h"
-
-#ifdef BENCHMARK_OS_WINDOWS
-#include <shlwapi.h>
-#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA
-#include <versionhelpers.h>
-#include <windows.h>
-#else
-#include <fcntl.h>
-#ifndef BENCHMARK_OS_FUCHSIA
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#include <sys/types.h> // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD
-#include <unistd.h>
-#if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX
-#include <sys/sysctl.h>
-#endif
-#if defined(BENCHMARK_OS_MACOSX)
-#include <mach/mach_init.h>
-#include <mach/mach_port.h>
-#include <mach/thread_act.h>
-#endif
-#endif
-
-#ifdef BENCHMARK_OS_EMSCRIPTEN
-#include <emscripten.h>
-#endif
-
-#include <cerrno>
-#include <cstdint>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <iostream>
-#include <limits>
-#include <mutex>
-
-#include "check.h"
-#include "log.h"
-#include "sleep.h"
-#include "string_util.h"
-
-namespace benchmark {
-
-// Suppress unused warnings on helper functions.
-#if defined(__GNUC__)
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-namespace {
-#if defined(BENCHMARK_OS_WINDOWS)
-double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) {
- ULARGE_INTEGER kernel;
- ULARGE_INTEGER user;
- kernel.HighPart = kernel_time.dwHighDateTime;
- kernel.LowPart = kernel_time.dwLowDateTime;
- user.HighPart = user_time.dwHighDateTime;
- user.LowPart = user_time.dwLowDateTime;
- return (static_cast<double>(kernel.QuadPart) +
- static_cast<double>(user.QuadPart)) *
- 1e-7;
-}
-#elif !defined(BENCHMARK_OS_FUCHSIA)
-double MakeTime(struct rusage const& ru) {
- return (static_cast<double>(ru.ru_utime.tv_sec) +
- static_cast<double>(ru.ru_utime.tv_usec) * 1e-6 +
- static_cast<double>(ru.ru_stime.tv_sec) +
- static_cast<double>(ru.ru_stime.tv_usec) * 1e-6);
-}
-#endif
-#if defined(BENCHMARK_OS_MACOSX)
-double MakeTime(thread_basic_info_data_t const& info) {
- return (static_cast<double>(info.user_time.seconds) +
- static_cast<double>(info.user_time.microseconds) * 1e-6 +
- static_cast<double>(info.system_time.seconds) +
- static_cast<double>(info.system_time.microseconds) * 1e-6);
-}
-#endif
-#if defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_THREAD_CPUTIME_ID)
-double MakeTime(struct timespec const& ts) {
- return ts.tv_sec + (static_cast<double>(ts.tv_nsec) * 1e-9);
-}
-#endif
-
-BENCHMARK_NORETURN static void DiagnoseAndExit(const char* msg) {
- std::cerr << "ERROR: " << msg << std::endl;
- std::exit(EXIT_FAILURE);
-}
-
-} // end namespace
-
-double ProcessCPUUsage() {
-#if defined(BENCHMARK_OS_WINDOWS)
- HANDLE proc = GetCurrentProcess();
- FILETIME creation_time;
- FILETIME exit_time;
- FILETIME kernel_time;
- FILETIME user_time;
- if (GetProcessTimes(proc, &creation_time, &exit_time, &kernel_time,
- &user_time))
- return MakeTime(kernel_time, user_time);
- DiagnoseAndExit("GetProccessTimes() failed");
-#elif defined(BENCHMARK_OS_EMSCRIPTEN)
- // clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) returns 0 on Emscripten.
- // Use Emscripten-specific API. Reported CPU time would be exactly the
- // same as total time, but this is ok because there aren't long-latency
- // syncronous system calls in Emscripten.
- return emscripten_get_now() * 1e-3;
-#elif defined(CLOCK_PROCESS_CPUTIME_ID) && !defined(BENCHMARK_OS_MACOSX)
- // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
- // https://github.com/google/benchmark/pull/292
- struct timespec spec;
- if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &spec) == 0)
- return MakeTime(spec);
- DiagnoseAndExit("clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) failed");
-#else
- struct rusage ru;
- if (getrusage(RUSAGE_SELF, &ru) == 0) return MakeTime(ru);
- DiagnoseAndExit("getrusage(RUSAGE_SELF, ...) failed");
-#endif
-}
-
-double ThreadCPUUsage() {
-#if defined(BENCHMARK_OS_WINDOWS)
- HANDLE this_thread = GetCurrentThread();
- FILETIME creation_time;
- FILETIME exit_time;
- FILETIME kernel_time;
- FILETIME user_time;
- GetThreadTimes(this_thread, &creation_time, &exit_time, &kernel_time,
- &user_time);
- return MakeTime(kernel_time, user_time);
-#elif defined(BENCHMARK_OS_MACOSX)
- // FIXME We want to use clock_gettime, but its not available in MacOS 10.11. See
- // https://github.com/google/benchmark/pull/292
- mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
- thread_basic_info_data_t info;
- mach_port_t thread = pthread_mach_thread_np(pthread_self());
- if (thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count) ==
- KERN_SUCCESS) {
- return MakeTime(info);
- }
- DiagnoseAndExit("ThreadCPUUsage() failed when evaluating thread_info");
-#elif defined(BENCHMARK_OS_EMSCRIPTEN)
- // Emscripten doesn't support traditional threads
- return ProcessCPUUsage();
-#elif defined(BENCHMARK_OS_RTEMS)
- // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See
- // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c
- return ProcessCPUUsage();
-#elif defined(BENCHMARK_OS_SOLARIS)
- struct rusage ru;
- if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru);
- DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed");
-#elif defined(CLOCK_THREAD_CPUTIME_ID)
- struct timespec ts;
- if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts);
- DiagnoseAndExit("clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...) failed");
-#else
-#error Per-thread timing is not available on your system.
-#endif
-}
-
-namespace {
-
-std::string DateTimeString(bool local) {
- typedef std::chrono::system_clock Clock;
- std::time_t now = Clock::to_time_t(Clock::now());
- const std::size_t kStorageSize = 128;
- char storage[kStorageSize];
- std::size_t written;
-
- if (local) {
-#if defined(BENCHMARK_OS_WINDOWS)
- written =
- std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now));
-#else
- std::tm timeinfo;
- ::localtime_r(&now, &timeinfo);
- written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo);
-#endif
- } else {
-#if defined(BENCHMARK_OS_WINDOWS)
- written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now));
-#else
- std::tm timeinfo;
- ::gmtime_r(&now, &timeinfo);
- written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo);
-#endif
- }
- CHECK(written < kStorageSize);
- ((void)written); // prevent unused variable in optimized mode.
- return std::string(storage);
-}
-
-} // end namespace
-
-std::string LocalDateTimeString() { return DateTimeString(true); }
-
-} // end namespace benchmark
+++ /dev/null
-#ifndef BENCHMARK_TIMERS_H
-#define BENCHMARK_TIMERS_H
-
-#include <chrono>
-#include <string>
-
-namespace benchmark {
-
-// Return the CPU usage of the current process
-double ProcessCPUUsage();
-
-// Return the CPU usage of the children of the current process
-double ChildrenCPUUsage();
-
-// Return the CPU usage of the current thread
-double ThreadCPUUsage();
-
-#if defined(HAVE_STEADY_CLOCK)
-template <bool HighResIsSteady = std::chrono::high_resolution_clock::is_steady>
-struct ChooseSteadyClock {
- typedef std::chrono::high_resolution_clock type;
-};
-
-template <>
-struct ChooseSteadyClock<false> {
- typedef std::chrono::steady_clock type;
-};
-#endif
-
-struct ChooseClockType {
-#if defined(HAVE_STEADY_CLOCK)
- typedef ChooseSteadyClock<>::type type;
-#else
- typedef std::chrono::high_resolution_clock type;
-#endif
-};
-
-inline double ChronoClockNow() {
- typedef ChooseClockType::type ClockType;
- using FpSeconds = std::chrono::duration<double, std::chrono::seconds::period>;
- return FpSeconds(ClockType::now().time_since_epoch()).count();
-}
-
-std::string LocalDateTimeString();
-
-} // end namespace benchmark
-
-#endif // BENCHMARK_TIMERS_H
+++ /dev/null
-
-include(split_list)
-
-set(ASM_TEST_FLAGS "")
-check_cxx_compiler_flag(-O3 BENCHMARK_HAS_O3_FLAG)
-if (BENCHMARK_HAS_O3_FLAG)
- list(APPEND ASM_TEST_FLAGS -O3)
-endif()
-
-check_cxx_compiler_flag(-g0 BENCHMARK_HAS_G0_FLAG)
-if (BENCHMARK_HAS_G0_FLAG)
- list(APPEND ASM_TEST_FLAGS -g0)
-endif()
-
-check_cxx_compiler_flag(-fno-stack-protector BENCHMARK_HAS_FNO_STACK_PROTECTOR_FLAG)
-if (BENCHMARK_HAS_FNO_STACK_PROTECTOR_FLAG)
- list(APPEND ASM_TEST_FLAGS -fno-stack-protector)
-endif()
-
-split_list(ASM_TEST_FLAGS)
-string(TOUPPER "${CMAKE_CXX_COMPILER_ID}" ASM_TEST_COMPILER)
-
-macro(add_filecheck_test name)
- cmake_parse_arguments(ARG "" "" "CHECK_PREFIXES" ${ARGV})
- add_library(${name} OBJECT ${name}.cc)
- set_target_properties(${name} PROPERTIES COMPILE_FLAGS "-S ${ASM_TEST_FLAGS}")
- set(ASM_OUTPUT_FILE "${CMAKE_CURRENT_BINARY_DIR}/${name}.s")
- add_custom_target(copy_${name} ALL
- COMMAND ${PROJECT_SOURCE_DIR}/tools/strip_asm.py
- $<TARGET_OBJECTS:${name}>
- ${ASM_OUTPUT_FILE}
- BYPRODUCTS ${ASM_OUTPUT_FILE})
- add_dependencies(copy_${name} ${name})
- if (NOT ARG_CHECK_PREFIXES)
- set(ARG_CHECK_PREFIXES "CHECK")
- endif()
- foreach(prefix ${ARG_CHECK_PREFIXES})
- add_test(NAME run_${name}_${prefix}
- COMMAND
- ${LLVM_FILECHECK_EXE} ${name}.cc
- --input-file=${ASM_OUTPUT_FILE}
- --check-prefixes=CHECK,CHECK-${ASM_TEST_COMPILER}
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
- endforeach()
-endmacro()
-
+++ /dev/null
-TEST_COPTS = [
- "-pedantic",
- "-pedantic-errors",
- "-std=c++11",
- "-Wall",
- "-Wextra",
- "-Wshadow",
- # "-Wshorten-64-to-32",
- "-Wfloat-equal",
- "-fstrict-aliasing",
-]
-
-PER_SRC_COPTS = ({
- "cxx03_test.cc": ["-std=c++03"],
- # Some of the issues with DoNotOptimize only occur when optimization is enabled
- "donotoptimize_test.cc": ["-O3"],
-})
-
-TEST_ARGS = ["--benchmark_min_time=0.01"]
-
-PER_SRC_TEST_ARGS = ({
- "user_counters_tabular_test.cc": ["--benchmark_counters_tabular=true"],
-})
-
-load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
-
-cc_library(
- name = "output_test_helper",
- testonly = 1,
- srcs = ["output_test_helper.cc"],
- hdrs = ["output_test.h"],
- copts = TEST_COPTS,
- deps = [
- "//:benchmark",
- "//:benchmark_internal_headers",
- ],
-)
-
-[
- cc_test(
- name = test_src[:-len(".cc")],
- size = "small",
- srcs = [test_src],
- args = TEST_ARGS + PER_SRC_TEST_ARGS.get(test_src, []),
- copts = TEST_COPTS + PER_SRC_COPTS.get(test_src, []),
- deps = [
- ":output_test_helper",
- "//:benchmark",
- "//:benchmark_internal_headers",
- "@com_google_googletest//:gtest",
- ] + (
- ["@com_google_googletest//:gtest_main"] if (test_src[-len("gtest.cc"):] == "gtest.cc") else []
- ),
- # FIXME: Add support for assembly tests to bazel.
- # See Issue #556
- # https://github.com/google/benchmark/issues/556
- )
- for test_src in glob(
- ["*test.cc"],
- exclude = [
- "*_assembly_test.cc",
- "link_main_test.cc",
- ],
- )
-]
-
-cc_test(
- name = "link_main_test",
- size = "small",
- srcs = ["link_main_test.cc"],
- copts = TEST_COPTS,
- deps = ["//:benchmark_main"],
-)
+++ /dev/null
-# Enable the tests
-
-find_package(Threads REQUIRED)
-include(CheckCXXCompilerFlag)
-
-# NOTE: Some tests use `<cassert>` to perform the test. Therefore we must
-# strip -DNDEBUG from the default CMake flags in DEBUG mode.
-string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
-if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" )
- add_definitions( -UNDEBUG )
- add_definitions(-DTEST_BENCHMARK_LIBRARY_HAS_NO_ASSERTIONS)
- # Also remove /D NDEBUG to avoid MSVC warnings about conflicting defines.
- foreach (flags_var_to_scrub
- CMAKE_CXX_FLAGS_RELEASE
- CMAKE_CXX_FLAGS_RELWITHDEBINFO
- CMAKE_CXX_FLAGS_MINSIZEREL
- CMAKE_C_FLAGS_RELEASE
- CMAKE_C_FLAGS_RELWITHDEBINFO
- CMAKE_C_FLAGS_MINSIZEREL)
- string (REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " "
- "${flags_var_to_scrub}" "${${flags_var_to_scrub}}")
- endforeach()
-endif()
-
-check_cxx_compiler_flag(-O3 BENCHMARK_HAS_O3_FLAG)
-set(BENCHMARK_O3_FLAG "")
-if (BENCHMARK_HAS_O3_FLAG)
- set(BENCHMARK_O3_FLAG "-O3")
-endif()
-
-# NOTE: These flags must be added after find_package(Threads REQUIRED) otherwise
-# they will break the configuration check.
-if (DEFINED BENCHMARK_CXX_LINKER_FLAGS)
- list(APPEND CMAKE_EXE_LINKER_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS})
-endif()
-
-add_library(output_test_helper STATIC output_test_helper.cc output_test.h)
-
-macro(compile_benchmark_test name)
- add_executable(${name} "${name}.cc")
- target_link_libraries(${name} benchmark::benchmark ${CMAKE_THREAD_LIBS_INIT})
-endmacro(compile_benchmark_test)
-
-macro(compile_benchmark_test_with_main name)
- add_executable(${name} "${name}.cc")
- target_link_libraries(${name} benchmark::benchmark_main)
-endmacro(compile_benchmark_test_with_main)
-
-macro(compile_output_test name)
- add_executable(${name} "${name}.cc" output_test.h)
- target_link_libraries(${name} output_test_helper benchmark::benchmark
- ${BENCHMARK_CXX_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
-endmacro(compile_output_test)
-
-# Demonstration executable
-compile_benchmark_test(benchmark_test)
-add_test(NAME benchmark COMMAND benchmark_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(filter_test)
-macro(add_filter_test name filter expect)
- add_test(NAME ${name} COMMAND filter_test --benchmark_min_time=0.01 --benchmark_filter=${filter} ${expect})
- add_test(NAME ${name}_list_only COMMAND filter_test --benchmark_list_tests --benchmark_filter=${filter} ${expect})
-endmacro(add_filter_test)
-
-add_filter_test(filter_simple "Foo" 3)
-add_filter_test(filter_simple_negative "-Foo" 2)
-add_filter_test(filter_suffix "BM_.*" 4)
-add_filter_test(filter_suffix_negative "-BM_.*" 1)
-add_filter_test(filter_regex_all ".*" 5)
-add_filter_test(filter_regex_all_negative "-.*" 0)
-add_filter_test(filter_regex_blank "" 5)
-add_filter_test(filter_regex_blank_negative "-" 0)
-add_filter_test(filter_regex_none "monkey" 0)
-add_filter_test(filter_regex_none_negative "-monkey" 5)
-add_filter_test(filter_regex_wildcard ".*Foo.*" 3)
-add_filter_test(filter_regex_wildcard_negative "-.*Foo.*" 2)
-add_filter_test(filter_regex_begin "^BM_.*" 4)
-add_filter_test(filter_regex_begin_negative "-^BM_.*" 1)
-add_filter_test(filter_regex_begin2 "^N" 1)
-add_filter_test(filter_regex_begin2_negative "-^N" 4)
-add_filter_test(filter_regex_end ".*Ba$" 1)
-add_filter_test(filter_regex_end_negative "-.*Ba$" 4)
-
-compile_benchmark_test(options_test)
-add_test(NAME options_benchmarks COMMAND options_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(basic_test)
-add_test(NAME basic_benchmark COMMAND basic_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(diagnostics_test)
-add_test(NAME diagnostics_test COMMAND diagnostics_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(skip_with_error_test)
-add_test(NAME skip_with_error_test COMMAND skip_with_error_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(donotoptimize_test)
-# Some of the issues with DoNotOptimize only occur when optimization is enabled
-check_cxx_compiler_flag(-O3 BENCHMARK_HAS_O3_FLAG)
-if (BENCHMARK_HAS_O3_FLAG)
- set_target_properties(donotoptimize_test PROPERTIES COMPILE_FLAGS "-O3")
-endif()
-add_test(NAME donotoptimize_test COMMAND donotoptimize_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(fixture_test)
-add_test(NAME fixture_test COMMAND fixture_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(register_benchmark_test)
-add_test(NAME register_benchmark_test COMMAND register_benchmark_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(map_test)
-add_test(NAME map_test COMMAND map_test --benchmark_min_time=0.01)
-
-compile_benchmark_test(multiple_ranges_test)
-add_test(NAME multiple_ranges_test COMMAND multiple_ranges_test --benchmark_min_time=0.01)
-
-compile_benchmark_test_with_main(link_main_test)
-add_test(NAME link_main_test COMMAND link_main_test --benchmark_min_time=0.01)
-
-compile_output_test(reporter_output_test)
-add_test(NAME reporter_output_test COMMAND reporter_output_test --benchmark_min_time=0.01)
-
-compile_output_test(templated_fixture_test)
-add_test(NAME templated_fixture_test COMMAND templated_fixture_test --benchmark_min_time=0.01)
-
-compile_output_test(user_counters_test)
-add_test(NAME user_counters_test COMMAND user_counters_test --benchmark_min_time=0.01)
-
-compile_output_test(internal_threading_test)
-add_test(NAME internal_threading_test COMMAND internal_threading_test --benchmark_min_time=0.01)
-
-compile_output_test(report_aggregates_only_test)
-add_test(NAME report_aggregates_only_test COMMAND report_aggregates_only_test --benchmark_min_time=0.01)
-
-compile_output_test(display_aggregates_only_test)
-add_test(NAME display_aggregates_only_test COMMAND display_aggregates_only_test --benchmark_min_time=0.01)
-
-compile_output_test(user_counters_tabular_test)
-add_test(NAME user_counters_tabular_test COMMAND user_counters_tabular_test --benchmark_counters_tabular=true --benchmark_min_time=0.01)
-
-compile_output_test(user_counters_thousands_test)
-add_test(NAME user_counters_thousands_test COMMAND user_counters_thousands_test --benchmark_min_time=0.01)
-
-compile_output_test(memory_manager_test)
-add_test(NAME memory_manager_test COMMAND memory_manager_test --benchmark_min_time=0.01)
-
-check_cxx_compiler_flag(-std=c++03 BENCHMARK_HAS_CXX03_FLAG)
-if (BENCHMARK_HAS_CXX03_FLAG)
- compile_benchmark_test(cxx03_test)
- set_target_properties(cxx03_test
- PROPERTIES
- CXX_STANDARD 98
- CXX_STANDARD_REQUIRED YES)
- # libstdc++ provides different definitions within <map> between dialects. When
- # LTO is enabled and -Werror is specified GCC diagnoses this ODR violation
- # causing the test to fail to compile. To prevent this we explicitly disable
- # the warning.
- check_cxx_compiler_flag(-Wno-odr BENCHMARK_HAS_WNO_ODR)
- if (BENCHMARK_ENABLE_LTO AND BENCHMARK_HAS_WNO_ODR)
- set_target_properties(cxx03_test
- PROPERTIES
- LINK_FLAGS "-Wno-odr")
- endif()
- add_test(NAME cxx03 COMMAND cxx03_test --benchmark_min_time=0.01)
-endif()
-
-# Attempt to work around flaky test failures when running on Appveyor servers.
-if (DEFINED ENV{APPVEYOR})
- set(COMPLEXITY_MIN_TIME "0.5")
-else()
- set(COMPLEXITY_MIN_TIME "0.01")
-endif()
-compile_output_test(complexity_test)
-add_test(NAME complexity_benchmark COMMAND complexity_test --benchmark_min_time=${COMPLEXITY_MIN_TIME})
-
-###############################################################################
-# GoogleTest Unit Tests
-###############################################################################
-
-if (BENCHMARK_ENABLE_GTEST_TESTS)
- macro(compile_gtest name)
- add_executable(${name} "${name}.cc")
- target_link_libraries(${name} benchmark::benchmark
- gmock_main ${CMAKE_THREAD_LIBS_INIT})
- endmacro(compile_gtest)
-
- macro(add_gtest name)
- compile_gtest(${name})
- add_test(NAME ${name} COMMAND ${name})
- endmacro()
-
- add_gtest(benchmark_gtest)
- add_gtest(benchmark_name_gtest)
- add_gtest(commandlineflags_gtest)
- add_gtest(statistics_gtest)
- add_gtest(string_util_gtest)
-endif(BENCHMARK_ENABLE_GTEST_TESTS)
-
-###############################################################################
-# Assembly Unit Tests
-###############################################################################
-
-if (BENCHMARK_ENABLE_ASSEMBLY_TESTS)
- if (NOT LLVM_FILECHECK_EXE)
- message(FATAL_ERROR "LLVM FileCheck is required when including this file")
- endif()
- include(AssemblyTests.cmake)
- add_filecheck_test(donotoptimize_assembly_test)
- add_filecheck_test(state_assembly_test)
- add_filecheck_test(clobber_memory_assembly_test)
-endif()
-
-
-
-###############################################################################
-# Code Coverage Configuration
-###############################################################################
-
-# Add the coverage command(s)
-if(CMAKE_BUILD_TYPE)
- string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
-endif()
-if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage")
- find_program(GCOV gcov)
- find_program(LCOV lcov)
- find_program(GENHTML genhtml)
- find_program(CTEST ctest)
- if (GCOV AND LCOV AND GENHTML AND CTEST AND HAVE_CXX_FLAG_COVERAGE)
- add_custom_command(
- OUTPUT ${CMAKE_BINARY_DIR}/lcov/index.html
- COMMAND ${LCOV} -q -z -d .
- COMMAND ${LCOV} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o before.lcov -i
- COMMAND ${CTEST} --force-new-ctest-process
- COMMAND ${LCOV} -q --no-external -c -b "${CMAKE_SOURCE_DIR}" -d . -o after.lcov
- COMMAND ${LCOV} -q -a before.lcov -a after.lcov --output-file final.lcov
- COMMAND ${LCOV} -q -r final.lcov "'${CMAKE_SOURCE_DIR}/test/*'" -o final.lcov
- COMMAND ${GENHTML} final.lcov -o lcov --demangle-cpp --sort -p "${CMAKE_BINARY_DIR}" -t benchmark
- DEPENDS filter_test benchmark_test options_test basic_test fixture_test cxx03_test complexity_test
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
- COMMENT "Running LCOV"
- )
- add_custom_target(coverage
- DEPENDS ${CMAKE_BINARY_DIR}/lcov/index.html
- COMMENT "LCOV report at lcov/index.html"
- )
- message(STATUS "Coverage command added")
- else()
- if (HAVE_CXX_FLAG_COVERAGE)
- set(CXX_FLAG_COVERAGE_MESSAGE supported)
- else()
- set(CXX_FLAG_COVERAGE_MESSAGE unavailable)
- endif()
- message(WARNING
- "Coverage not available:\n"
- " gcov: ${GCOV}\n"
- " lcov: ${LCOV}\n"
- " genhtml: ${GENHTML}\n"
- " ctest: ${CTEST}\n"
- " --coverage flag: ${CXX_FLAG_COVERAGE_MESSAGE}")
- endif()
-endif()
+++ /dev/null
-
-#include "benchmark/benchmark.h"
-
-#define BASIC_BENCHMARK_TEST(x) BENCHMARK(x)->Arg(8)->Arg(512)->Arg(8192)
-
-void BM_empty(benchmark::State& state) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(state.iterations());
- }
-}
-BENCHMARK(BM_empty);
-BENCHMARK(BM_empty)->ThreadPerCpu();
-
-void BM_spin_empty(benchmark::State& state) {
- for (auto _ : state) {
- for (int x = 0; x < state.range(0); ++x) {
- benchmark::DoNotOptimize(x);
- }
- }
-}
-BASIC_BENCHMARK_TEST(BM_spin_empty);
-BASIC_BENCHMARK_TEST(BM_spin_empty)->ThreadPerCpu();
-
-void BM_spin_pause_before(benchmark::State& state) {
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- for (auto _ : state) {
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- }
-}
-BASIC_BENCHMARK_TEST(BM_spin_pause_before);
-BASIC_BENCHMARK_TEST(BM_spin_pause_before)->ThreadPerCpu();
-
-void BM_spin_pause_during(benchmark::State& state) {
- for (auto _ : state) {
- state.PauseTiming();
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- state.ResumeTiming();
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- }
-}
-BASIC_BENCHMARK_TEST(BM_spin_pause_during);
-BASIC_BENCHMARK_TEST(BM_spin_pause_during)->ThreadPerCpu();
-
-void BM_pause_during(benchmark::State& state) {
- for (auto _ : state) {
- state.PauseTiming();
- state.ResumeTiming();
- }
-}
-BENCHMARK(BM_pause_during);
-BENCHMARK(BM_pause_during)->ThreadPerCpu();
-BENCHMARK(BM_pause_during)->UseRealTime();
-BENCHMARK(BM_pause_during)->UseRealTime()->ThreadPerCpu();
-
-void BM_spin_pause_after(benchmark::State& state) {
- for (auto _ : state) {
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- }
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
-}
-BASIC_BENCHMARK_TEST(BM_spin_pause_after);
-BASIC_BENCHMARK_TEST(BM_spin_pause_after)->ThreadPerCpu();
-
-void BM_spin_pause_before_and_after(benchmark::State& state) {
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- for (auto _ : state) {
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
- }
- for (int i = 0; i < state.range(0); ++i) {
- benchmark::DoNotOptimize(i);
- }
-}
-BASIC_BENCHMARK_TEST(BM_spin_pause_before_and_after);
-BASIC_BENCHMARK_TEST(BM_spin_pause_before_and_after)->ThreadPerCpu();
-
-void BM_empty_stop_start(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_empty_stop_start);
-BENCHMARK(BM_empty_stop_start)->ThreadPerCpu();
-
-
-void BM_KeepRunning(benchmark::State& state) {
- benchmark::IterationCount iter_count = 0;
- assert(iter_count == state.iterations());
- while (state.KeepRunning()) {
- ++iter_count;
- }
- assert(iter_count == state.iterations());
-}
-BENCHMARK(BM_KeepRunning);
-
-void BM_KeepRunningBatch(benchmark::State& state) {
- // Choose a prime batch size to avoid evenly dividing max_iterations.
- const benchmark::IterationCount batch_size = 101;
- benchmark::IterationCount iter_count = 0;
- while (state.KeepRunningBatch(batch_size)) {
- iter_count += batch_size;
- }
- assert(state.iterations() == iter_count);
-}
-BENCHMARK(BM_KeepRunningBatch);
-
-void BM_RangedFor(benchmark::State& state) {
- benchmark::IterationCount iter_count = 0;
- for (auto _ : state) {
- ++iter_count;
- }
- assert(iter_count == state.max_iterations);
-}
-BENCHMARK(BM_RangedFor);
-
-// Ensure that StateIterator provides all the necessary typedefs required to
-// instantiate std::iterator_traits.
-static_assert(std::is_same<
- typename std::iterator_traits<benchmark::State::StateIterator>::value_type,
- typename benchmark::State::StateIterator::value_type>::value, "");
-
-BENCHMARK_MAIN();
+++ /dev/null
-#include <vector>
-
-#include "../src/benchmark_register.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace benchmark {
-namespace internal {
-namespace {
-
-TEST(AddRangeTest, Simple) {
- std::vector<int> dst;
- AddRange(&dst, 1, 2, 2);
- EXPECT_THAT(dst, testing::ElementsAre(1, 2));
-}
-
-TEST(AddRangeTest, Simple64) {
- std::vector<int64_t> dst;
- AddRange(&dst, static_cast<int64_t>(1), static_cast<int64_t>(2), 2);
- EXPECT_THAT(dst, testing::ElementsAre(1, 2));
-}
-
-TEST(AddRangeTest, Advanced) {
- std::vector<int> dst;
- AddRange(&dst, 5, 15, 2);
- EXPECT_THAT(dst, testing::ElementsAre(5, 8, 15));
-}
-
-TEST(AddRangeTest, Advanced64) {
- std::vector<int64_t> dst;
- AddRange(&dst, static_cast<int64_t>(5), static_cast<int64_t>(15), 2);
- EXPECT_THAT(dst, testing::ElementsAre(5, 8, 15));
-}
-
-TEST(AddRangeTest, FullRange8) {
- std::vector<int8_t> dst;
- AddRange(&dst, int8_t{1}, std::numeric_limits<int8_t>::max(), 8);
- EXPECT_THAT(dst, testing::ElementsAre(1, 8, 64, 127));
-}
-
-TEST(AddRangeTest, FullRange64) {
- std::vector<int64_t> dst;
- AddRange(&dst, int64_t{1}, std::numeric_limits<int64_t>::max(), 1024);
- EXPECT_THAT(
- dst, testing::ElementsAre(1LL, 1024LL, 1048576LL, 1073741824LL,
- 1099511627776LL, 1125899906842624LL,
- 1152921504606846976LL, 9223372036854775807LL));
-}
-
-TEST(AddRangeTest, NegativeRanges) {
- std::vector<int> dst;
- AddRange(&dst, -8, 0, 2);
- EXPECT_THAT(dst, testing::ElementsAre(-8, -4, -2, -1, 0));
-}
-
-TEST(AddRangeTest, StrictlyNegative) {
- std::vector<int> dst;
- AddRange(&dst, -8, -1, 2);
- EXPECT_THAT(dst, testing::ElementsAre(-8, -4, -2, -1));
-}
-
-TEST(AddRangeTest, SymmetricNegativeRanges) {
- std::vector<int> dst;
- AddRange(&dst, -8, 8, 2);
- EXPECT_THAT(dst, testing::ElementsAre(-8, -4, -2, -1, 0, 1, 2, 4, 8));
-}
-
-TEST(AddRangeTest, SymmetricNegativeRangesOddMult) {
- std::vector<int> dst;
- AddRange(&dst, -30, 32, 5);
- EXPECT_THAT(dst, testing::ElementsAre(-30, -25, -5, -1, 0, 1, 5, 25, 32));
-}
-
-TEST(AddRangeTest, NegativeRangesAsymmetric) {
- std::vector<int> dst;
- AddRange(&dst, -3, 5, 2);
- EXPECT_THAT(dst, testing::ElementsAre(-3, -2, -1, 0, 1, 2, 4, 5));
-}
-
-TEST(AddRangeTest, NegativeRangesLargeStep) {
- // Always include -1, 0, 1 when crossing zero.
- std::vector<int> dst;
- AddRange(&dst, -8, 8, 10);
- EXPECT_THAT(dst, testing::ElementsAre(-8, -1, 0, 1, 8));
-}
-
-TEST(AddRangeTest, ZeroOnlyRange) {
- std::vector<int> dst;
- AddRange(&dst, 0, 0, 2);
- EXPECT_THAT(dst, testing::ElementsAre(0));
-}
-
-TEST(AddRangeTest, NegativeRange64) {
- std::vector<int64_t> dst;
- AddRange<int64_t>(&dst, -4, 4, 2);
- EXPECT_THAT(dst, testing::ElementsAre(-4, -2, -1, 0, 1, 2, 4));
-}
-
-TEST(AddRangeTest, NegativeRangePreservesExistingOrder) {
- // If elements already exist in the range, ensure we don't change
- // their ordering by adding negative values.
- std::vector<int64_t> dst = {1, 2, 3};
- AddRange<int64_t>(&dst, -2, 2, 2);
- EXPECT_THAT(dst, testing::ElementsAre(1, 2, 3, -2, -1, 0, 1, 2));
-}
-
-TEST(AddRangeTest, FullNegativeRange64) {
- std::vector<int64_t> dst;
- const auto min = std::numeric_limits<int64_t>::min();
- const auto max = std::numeric_limits<int64_t>::max();
- AddRange(&dst, min, max, 1024);
- EXPECT_THAT(
- dst, testing::ElementsAreArray(std::vector<int64_t>{
- min, -1152921504606846976LL, -1125899906842624LL,
- -1099511627776LL, -1073741824LL, -1048576LL, -1024LL, -1LL, 0LL,
- 1LL, 1024LL, 1048576LL, 1073741824LL, 1099511627776LL,
- 1125899906842624LL, 1152921504606846976LL, max}));
-}
-
-TEST(AddRangeTest, Simple8) {
- std::vector<int8_t> dst;
- AddRange<int8_t>(&dst, 1, 8, 2);
- EXPECT_THAT(dst, testing::ElementsAre(1, 2, 4, 8));
-}
-
-} // namespace
-} // namespace internal
-} // namespace benchmark
+++ /dev/null
-#include "benchmark/benchmark.h"
-#include "gtest/gtest.h"
-
-namespace {
-
-using namespace benchmark;
-using namespace benchmark::internal;
-
-TEST(BenchmarkNameTest, Empty) {
- const auto name = BenchmarkName();
- EXPECT_EQ(name.str(), std::string());
-}
-
-TEST(BenchmarkNameTest, FunctionName) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- EXPECT_EQ(name.str(), "function_name");
-}
-
-TEST(BenchmarkNameTest, FunctionNameAndArgs) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- name.args = "some_args:3/4/5";
- EXPECT_EQ(name.str(), "function_name/some_args:3/4/5");
-}
-
-TEST(BenchmarkNameTest, MinTime) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- name.args = "some_args:3/4";
- name.min_time = "min_time:3.4s";
- EXPECT_EQ(name.str(), "function_name/some_args:3/4/min_time:3.4s");
-}
-
-TEST(BenchmarkNameTest, Iterations) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- name.min_time = "min_time:3.4s";
- name.iterations = "iterations:42";
- EXPECT_EQ(name.str(), "function_name/min_time:3.4s/iterations:42");
-}
-
-TEST(BenchmarkNameTest, Repetitions) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- name.min_time = "min_time:3.4s";
- name.repetitions = "repetitions:24";
- EXPECT_EQ(name.str(), "function_name/min_time:3.4s/repetitions:24");
-}
-
-TEST(BenchmarkNameTest, TimeType) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- name.min_time = "min_time:3.4s";
- name.time_type = "hammer_time";
- EXPECT_EQ(name.str(), "function_name/min_time:3.4s/hammer_time");
-}
-
-TEST(BenchmarkNameTest, Threads) {
- auto name = BenchmarkName();
- name.function_name = "function_name";
- name.min_time = "min_time:3.4s";
- name.threads = "threads:256";
- EXPECT_EQ(name.str(), "function_name/min_time:3.4s/threads:256");
-}
-
-TEST(BenchmarkNameTest, TestEmptyFunctionName) {
- auto name = BenchmarkName();
- name.args = "first:3/second:4";
- name.threads = "threads:22";
- EXPECT_EQ(name.str(), "first:3/second:4/threads:22");
-}
-
-} // end namespace
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-#include <assert.h>
-#include <math.h>
-#include <stdint.h>
-
-#include <chrono>
-#include <cstdlib>
-#include <iostream>
-#include <limits>
-#include <list>
-#include <map>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <string>
-#include <thread>
-#include <utility>
-#include <vector>
-
-#if defined(__GNUC__)
-#define BENCHMARK_NOINLINE __attribute__((noinline))
-#else
-#define BENCHMARK_NOINLINE
-#endif
-
-namespace {
-
-int BENCHMARK_NOINLINE Factorial(uint32_t n) {
- return (n == 1) ? 1 : n * Factorial(n - 1);
-}
-
-double CalculatePi(int depth) {
- double pi = 0.0;
- for (int i = 0; i < depth; ++i) {
- double numerator = static_cast<double>(((i % 2) * 2) - 1);
- double denominator = static_cast<double>((2 * i) - 1);
- pi += numerator / denominator;
- }
- return (pi - 1.0) * 4;
-}
-
-std::set<int64_t> ConstructRandomSet(int64_t size) {
- std::set<int64_t> s;
- for (int i = 0; i < size; ++i) s.insert(s.end(), i);
- return s;
-}
-
-std::mutex test_vector_mu;
-std::vector<int>* test_vector = nullptr;
-
-} // end namespace
-
-static void BM_Factorial(benchmark::State& state) {
- int fac_42 = 0;
- for (auto _ : state) fac_42 = Factorial(8);
- // Prevent compiler optimizations
- std::stringstream ss;
- ss << fac_42;
- state.SetLabel(ss.str());
-}
-BENCHMARK(BM_Factorial);
-BENCHMARK(BM_Factorial)->UseRealTime();
-
-static void BM_CalculatePiRange(benchmark::State& state) {
- double pi = 0.0;
- for (auto _ : state) pi = CalculatePi(static_cast<int>(state.range(0)));
- std::stringstream ss;
- ss << pi;
- state.SetLabel(ss.str());
-}
-BENCHMARK_RANGE(BM_CalculatePiRange, 1, 1024 * 1024);
-
-static void BM_CalculatePi(benchmark::State& state) {
- static const int depth = 1024;
- for (auto _ : state) {
- benchmark::DoNotOptimize(CalculatePi(static_cast<int>(depth)));
- }
-}
-BENCHMARK(BM_CalculatePi)->Threads(8);
-BENCHMARK(BM_CalculatePi)->ThreadRange(1, 32);
-BENCHMARK(BM_CalculatePi)->ThreadPerCpu();
-
-static void BM_SetInsert(benchmark::State& state) {
- std::set<int64_t> data;
- for (auto _ : state) {
- state.PauseTiming();
- data = ConstructRandomSet(state.range(0));
- state.ResumeTiming();
- for (int j = 0; j < state.range(1); ++j) data.insert(rand());
- }
- state.SetItemsProcessed(state.iterations() * state.range(1));
- state.SetBytesProcessed(state.iterations() * state.range(1) * sizeof(int));
-}
-
-// Test many inserts at once to reduce the total iterations needed. Otherwise, the slower,
-// non-timed part of each iteration will make the benchmark take forever.
-BENCHMARK(BM_SetInsert)->Ranges({{1 << 10, 8 << 10}, {128, 512}});
-
-template <typename Container,
- typename ValueType = typename Container::value_type>
-static void BM_Sequential(benchmark::State& state) {
- ValueType v = 42;
- for (auto _ : state) {
- Container c;
- for (int64_t i = state.range(0); --i;) c.push_back(v);
- }
- const int64_t items_processed = state.iterations() * state.range(0);
- state.SetItemsProcessed(items_processed);
- state.SetBytesProcessed(items_processed * sizeof(v));
-}
-BENCHMARK_TEMPLATE2(BM_Sequential, std::vector<int>, int)
- ->Range(1 << 0, 1 << 10);
-BENCHMARK_TEMPLATE(BM_Sequential, std::list<int>)->Range(1 << 0, 1 << 10);
-// Test the variadic version of BENCHMARK_TEMPLATE in C++11 and beyond.
-#ifdef BENCHMARK_HAS_CXX11
-BENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>, int)->Arg(512);
-#endif
-
-static void BM_StringCompare(benchmark::State& state) {
- size_t len = static_cast<size_t>(state.range(0));
- std::string s1(len, '-');
- std::string s2(len, '-');
- for (auto _ : state) benchmark::DoNotOptimize(s1.compare(s2));
-}
-BENCHMARK(BM_StringCompare)->Range(1, 1 << 20);
-
-static void BM_SetupTeardown(benchmark::State& state) {
- if (state.thread_index == 0) {
- // No need to lock test_vector_mu here as this is running single-threaded.
- test_vector = new std::vector<int>();
- }
- int i = 0;
- for (auto _ : state) {
- std::lock_guard<std::mutex> l(test_vector_mu);
- if (i % 2 == 0)
- test_vector->push_back(i);
- else
- test_vector->pop_back();
- ++i;
- }
- if (state.thread_index == 0) {
- delete test_vector;
- }
-}
-BENCHMARK(BM_SetupTeardown)->ThreadPerCpu();
-
-static void BM_LongTest(benchmark::State& state) {
- double tracker = 0.0;
- for (auto _ : state) {
- for (int i = 0; i < state.range(0); ++i)
- benchmark::DoNotOptimize(tracker += i);
- }
-}
-BENCHMARK(BM_LongTest)->Range(1 << 16, 1 << 28);
-
-static void BM_ParallelMemset(benchmark::State& state) {
- int64_t size = state.range(0) / static_cast<int64_t>(sizeof(int));
- int thread_size = static_cast<int>(size) / state.threads;
- int from = thread_size * state.thread_index;
- int to = from + thread_size;
-
- if (state.thread_index == 0) {
- test_vector = new std::vector<int>(static_cast<size_t>(size));
- }
-
- for (auto _ : state) {
- for (int i = from; i < to; i++) {
- // No need to lock test_vector_mu as ranges
- // do not overlap between threads.
- benchmark::DoNotOptimize(test_vector->at(i) = 1);
- }
- }
-
- if (state.thread_index == 0) {
- delete test_vector;
- }
-}
-BENCHMARK(BM_ParallelMemset)->Arg(10 << 20)->ThreadRange(1, 4);
-
-static void BM_ManualTiming(benchmark::State& state) {
- int64_t slept_for = 0;
- int64_t microseconds = state.range(0);
- std::chrono::duration<double, std::micro> sleep_duration{
- static_cast<double>(microseconds)};
-
- for (auto _ : state) {
- auto start = std::chrono::high_resolution_clock::now();
- // Simulate some useful workload with a sleep
- std::this_thread::sleep_for(
- std::chrono::duration_cast<std::chrono::nanoseconds>(sleep_duration));
- auto end = std::chrono::high_resolution_clock::now();
-
- auto elapsed =
- std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
-
- state.SetIterationTime(elapsed.count());
- slept_for += microseconds;
- }
- state.SetItemsProcessed(slept_for);
-}
-BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseRealTime();
-BENCHMARK(BM_ManualTiming)->Range(1, 1 << 14)->UseManualTime();
-
-#ifdef BENCHMARK_HAS_CXX11
-
-template <class... Args>
-void BM_with_args(benchmark::State& state, Args&&...) {
- for (auto _ : state) {
- }
-}
-BENCHMARK_CAPTURE(BM_with_args, int_test, 42, 43, 44);
-BENCHMARK_CAPTURE(BM_with_args, string_and_pair_test, std::string("abc"),
- std::pair<int, double>(42, 3.8));
-
-void BM_non_template_args(benchmark::State& state, int, double) {
- while(state.KeepRunning()) {}
-}
-BENCHMARK_CAPTURE(BM_non_template_args, basic_test, 0, 0);
-
-#endif // BENCHMARK_HAS_CXX11
-
-static void BM_DenseThreadRanges(benchmark::State& st) {
- switch (st.range(0)) {
- case 1:
- assert(st.threads == 1 || st.threads == 2 || st.threads == 3);
- break;
- case 2:
- assert(st.threads == 1 || st.threads == 3 || st.threads == 4);
- break;
- case 3:
- assert(st.threads == 5 || st.threads == 8 || st.threads == 11 ||
- st.threads == 14);
- break;
- default:
- assert(false && "Invalid test case number");
- }
- while (st.KeepRunning()) {
- }
-}
-BENCHMARK(BM_DenseThreadRanges)->Arg(1)->DenseThreadRange(1, 3);
-BENCHMARK(BM_DenseThreadRanges)->Arg(2)->DenseThreadRange(1, 4, 2);
-BENCHMARK(BM_DenseThreadRanges)->Arg(3)->DenseThreadRange(5, 14, 3);
-
-BENCHMARK_MAIN();
+++ /dev/null
-#include <benchmark/benchmark.h>
-
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wreturn-type"
-#endif
-
-extern "C" {
-
-extern int ExternInt;
-extern int ExternInt2;
-extern int ExternInt3;
-
-}
-
-// CHECK-LABEL: test_basic:
-extern "C" void test_basic() {
- int x;
- benchmark::DoNotOptimize(&x);
- x = 101;
- benchmark::ClobberMemory();
- // CHECK: leaq [[DEST:[^,]+]], %rax
- // CHECK: movl $101, [[DEST]]
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_redundant_store:
-extern "C" void test_redundant_store() {
- ExternInt = 3;
- benchmark::ClobberMemory();
- ExternInt = 51;
- // CHECK-DAG: ExternInt
- // CHECK-DAG: movl $3
- // CHECK: movl $51
-}
-
-// CHECK-LABEL: test_redundant_read:
-extern "C" void test_redundant_read() {
- int x;
- benchmark::DoNotOptimize(&x);
- x = ExternInt;
- benchmark::ClobberMemory();
- x = ExternInt2;
- // CHECK: leaq [[DEST:[^,]+]], %rax
- // CHECK: ExternInt(%rip)
- // CHECK: movl %eax, [[DEST]]
- // CHECK-NOT: ExternInt2
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_redundant_read2:
-extern "C" void test_redundant_read2() {
- int x;
- benchmark::DoNotOptimize(&x);
- x = ExternInt;
- benchmark::ClobberMemory();
- x = ExternInt2;
- benchmark::ClobberMemory();
- // CHECK: leaq [[DEST:[^,]+]], %rax
- // CHECK: ExternInt(%rip)
- // CHECK: movl %eax, [[DEST]]
- // CHECK: ExternInt2(%rip)
- // CHECK: movl %eax, [[DEST]]
- // CHECK: ret
-}
+++ /dev/null
-#include <cstdlib>
-
-#include "../src/commandlineflags.h"
-#include "../src/internal_macros.h"
-#include "gtest/gtest.h"
-
-namespace benchmark {
-namespace {
-
-#if defined(BENCHMARK_OS_WINDOWS)
-int setenv(const char* name, const char* value, int overwrite) {
- if (!overwrite) {
- // NOTE: getenv_s is far superior but not available under mingw.
- char* env_value = getenv(name);
- if (env_value == nullptr) {
- return -1;
- }
- }
- return _putenv_s(name, value);
-}
-
-int unsetenv(const char* name) {
- return _putenv_s(name, "");
-}
-
-#endif // BENCHMARK_OS_WINDOWS
-
-TEST(BoolFromEnv, Default) {
- ASSERT_EQ(unsetenv("BENCHMARK_NOT_IN_ENV"), 0);
- EXPECT_EQ(BoolFromEnv("not_in_env", true), true);
-}
-
-TEST(BoolFromEnv, False) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "0", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "N", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "n", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "NO", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "No", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "no", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "F", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "f", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "FALSE", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "False", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "false", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "OFF", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "Off", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "off", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", true), false);
- unsetenv("BENCHMARK_IN_ENV");
-}
-
-TEST(BoolFromEnv, True) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "1", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "Y", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "y", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "YES", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "Yes", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "yes", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "T", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "t", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "TRUE", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "True", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "true", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "ON", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "On", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "on", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-
-#ifndef BENCHMARK_OS_WINDOWS
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "", 1), 0);
- EXPECT_EQ(BoolFromEnv("in_env", false), true);
- unsetenv("BENCHMARK_IN_ENV");
-#endif
-}
-
-TEST(Int32FromEnv, NotInEnv) {
- ASSERT_EQ(unsetenv("BENCHMARK_NOT_IN_ENV"), 0);
- EXPECT_EQ(Int32FromEnv("not_in_env", 42), 42);
-}
-
-TEST(Int32FromEnv, InvalidInteger) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "foo", 1), 0);
- EXPECT_EQ(Int32FromEnv("in_env", 42), 42);
- unsetenv("BENCHMARK_IN_ENV");
-}
-
-TEST(Int32FromEnv, ValidInteger) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "42", 1), 0);
- EXPECT_EQ(Int32FromEnv("in_env", 64), 42);
- unsetenv("BENCHMARK_IN_ENV");
-}
-
-TEST(DoubleFromEnv, NotInEnv) {
- ASSERT_EQ(unsetenv("BENCHMARK_NOT_IN_ENV"), 0);
- EXPECT_EQ(DoubleFromEnv("not_in_env", 0.51), 0.51);
-}
-
-TEST(DoubleFromEnv, InvalidReal) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "foo", 1), 0);
- EXPECT_EQ(DoubleFromEnv("in_env", 0.51), 0.51);
- unsetenv("BENCHMARK_IN_ENV");
-}
-
-TEST(DoubleFromEnv, ValidReal) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "0.51", 1), 0);
- EXPECT_EQ(DoubleFromEnv("in_env", 0.71), 0.51);
- unsetenv("BENCHMARK_IN_ENV");
-}
-
-TEST(StringFromEnv, Default) {
- ASSERT_EQ(unsetenv("BENCHMARK_NOT_IN_ENV"), 0);
- EXPECT_STREQ(StringFromEnv("not_in_env", "foo"), "foo");
-}
-
-TEST(StringFromEnv, Valid) {
- ASSERT_EQ(setenv("BENCHMARK_IN_ENV", "foo", 1), 0);
- EXPECT_STREQ(StringFromEnv("in_env", "bar"), "foo");
- unsetenv("BENCHMARK_IN_ENV");
-}
-
-} // namespace
-} // namespace benchmark
+++ /dev/null
-#undef NDEBUG
-#include <algorithm>
-#include <cassert>
-#include <cmath>
-#include <cstdlib>
-#include <vector>
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-namespace {
-
-#define ADD_COMPLEXITY_CASES(...) \
- int CONCAT(dummy, __LINE__) = AddComplexityTest(__VA_ARGS__)
-
-int AddComplexityTest(std::string test_name, std::string big_o_test_name,
- std::string rms_test_name, std::string big_o) {
- SetSubstitutions({{"%name", test_name},
- {"%bigo_name", big_o_test_name},
- {"%rms_name", rms_test_name},
- {"%bigo_str", "[ ]* %float " + big_o},
- {"%bigo", big_o},
- {"%rms", "[ ]*[0-9]+ %"}});
- AddCases(
- TC_ConsoleOut,
- {{"^%bigo_name %bigo_str %bigo_str[ ]*$"},
- {"^%bigo_name", MR_Not}, // Assert we we didn't only matched a name.
- {"^%rms_name %rms %rms[ ]*$", MR_Next}});
- AddCases(TC_JSONOut, {{"\"name\": \"%bigo_name\",$"},
- {"\"run_name\": \"%name\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": %int,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"BigO\",$", MR_Next},
- {"\"cpu_coefficient\": %float,$", MR_Next},
- {"\"real_coefficient\": %float,$", MR_Next},
- {"\"big_o\": \"%bigo\",$", MR_Next},
- {"\"time_unit\": \"ns\"$", MR_Next},
- {"}", MR_Next},
- {"\"name\": \"%rms_name\",$"},
- {"\"run_name\": \"%name\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": %int,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"RMS\",$", MR_Next},
- {"\"rms\": %float$", MR_Next},
- {"}", MR_Next}});
- AddCases(TC_CSVOut, {{"^\"%bigo_name\",,%float,%float,%bigo,,,,,$"},
- {"^\"%bigo_name\"", MR_Not},
- {"^\"%rms_name\",,%float,%float,,,,,,$", MR_Next}});
- return 0;
-}
-
-} // end namespace
-
-// ========================================================================= //
-// --------------------------- Testing BigO O(1) --------------------------- //
-// ========================================================================= //
-
-void BM_Complexity_O1(benchmark::State& state) {
- for (auto _ : state) {
- for (int i = 0; i < 1024; ++i) {
- benchmark::DoNotOptimize(&i);
- }
- }
- state.SetComplexityN(state.range(0));
-}
-BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(benchmark::o1);
-BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity();
-BENCHMARK(BM_Complexity_O1)
- ->Range(1, 1 << 18)
- ->Complexity([](benchmark::IterationCount) { return 1.0; });
-
-const char *one_test_name = "BM_Complexity_O1";
-const char *big_o_1_test_name = "BM_Complexity_O1_BigO";
-const char *rms_o_1_test_name = "BM_Complexity_O1_RMS";
-const char *enum_big_o_1 = "\\([0-9]+\\)";
-// FIXME: Tolerate both '(1)' and 'lgN' as output when the complexity is auto
-// deduced.
-// See https://github.com/google/benchmark/issues/272
-const char *auto_big_o_1 = "(\\([0-9]+\\))|(lgN)";
-const char *lambda_big_o_1 = "f\\(N\\)";
-
-// Add enum tests
-ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
- enum_big_o_1);
-
-// Add auto enum tests
-ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
- auto_big_o_1);
-
-// Add lambda tests
-ADD_COMPLEXITY_CASES(one_test_name, big_o_1_test_name, rms_o_1_test_name,
- lambda_big_o_1);
-
-// ========================================================================= //
-// --------------------------- Testing BigO O(N) --------------------------- //
-// ========================================================================= //
-
-std::vector<int> ConstructRandomVector(int64_t size) {
- std::vector<int> v;
- v.reserve(static_cast<int>(size));
- for (int i = 0; i < size; ++i) {
- v.push_back(static_cast<int>(std::rand() % size));
- }
- return v;
-}
-
-void BM_Complexity_O_N(benchmark::State& state) {
- auto v = ConstructRandomVector(state.range(0));
- // Test worst case scenario (item not in vector)
- const int64_t item_not_in_vector = state.range(0) * 2;
- for (auto _ : state) {
- benchmark::DoNotOptimize(std::find(v.begin(), v.end(), item_not_in_vector));
- }
- state.SetComplexityN(state.range(0));
-}
-BENCHMARK(BM_Complexity_O_N)
- ->RangeMultiplier(2)
- ->Range(1 << 10, 1 << 16)
- ->Complexity(benchmark::oN);
-BENCHMARK(BM_Complexity_O_N)
- ->RangeMultiplier(2)
- ->Range(1 << 10, 1 << 16)
- ->Complexity([](benchmark::IterationCount n) -> double {
- return static_cast<double>(n);
- });
-BENCHMARK(BM_Complexity_O_N)
- ->RangeMultiplier(2)
- ->Range(1 << 10, 1 << 16)
- ->Complexity();
-
-const char *n_test_name = "BM_Complexity_O_N";
-const char *big_o_n_test_name = "BM_Complexity_O_N_BigO";
-const char *rms_o_n_test_name = "BM_Complexity_O_N_RMS";
-const char *enum_auto_big_o_n = "N";
-const char *lambda_big_o_n = "f\\(N\\)";
-
-// Add enum tests
-ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
- enum_auto_big_o_n);
-
-// Add lambda tests
-ADD_COMPLEXITY_CASES(n_test_name, big_o_n_test_name, rms_o_n_test_name,
- lambda_big_o_n);
-
-// ========================================================================= //
-// ------------------------- Testing BigO O(N*lgN) ------------------------- //
-// ========================================================================= //
-
-static void BM_Complexity_O_N_log_N(benchmark::State& state) {
- auto v = ConstructRandomVector(state.range(0));
- for (auto _ : state) {
- std::sort(v.begin(), v.end());
- }
- state.SetComplexityN(state.range(0));
-}
-static const double kLog2E = 1.44269504088896340736;
-BENCHMARK(BM_Complexity_O_N_log_N)
- ->RangeMultiplier(2)
- ->Range(1 << 10, 1 << 16)
- ->Complexity(benchmark::oNLogN);
-BENCHMARK(BM_Complexity_O_N_log_N)
- ->RangeMultiplier(2)
- ->Range(1 << 10, 1 << 16)
- ->Complexity([](benchmark::IterationCount n) {
- return kLog2E * n * log(static_cast<double>(n));
- });
-BENCHMARK(BM_Complexity_O_N_log_N)
- ->RangeMultiplier(2)
- ->Range(1 << 10, 1 << 16)
- ->Complexity();
-
-const char *n_lg_n_test_name = "BM_Complexity_O_N_log_N";
-const char *big_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_BigO";
-const char *rms_o_n_lg_n_test_name = "BM_Complexity_O_N_log_N_RMS";
-const char *enum_auto_big_o_n_lg_n = "NlgN";
-const char *lambda_big_o_n_lg_n = "f\\(N\\)";
-
-// Add enum tests
-ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
- rms_o_n_lg_n_test_name, enum_auto_big_o_n_lg_n);
-
-// Add lambda tests
-ADD_COMPLEXITY_CASES(n_lg_n_test_name, big_o_n_lg_n_test_name,
- rms_o_n_lg_n_test_name, lambda_big_o_n_lg_n);
-
-// ========================================================================= //
-// -------- Testing formatting of Complexity with captured args ------------ //
-// ========================================================================= //
-
-void BM_ComplexityCaptureArgs(benchmark::State& state, int n) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- state.SetComplexityN(n);
-}
-
-BENCHMARK_CAPTURE(BM_ComplexityCaptureArgs, capture_test, 100)
- ->Complexity(benchmark::oN)
- ->Ranges({{1, 2}, {3, 4}});
-
-const std::string complexity_capture_name =
- "BM_ComplexityCaptureArgs/capture_test";
-
-ADD_COMPLEXITY_CASES(complexity_capture_name, complexity_capture_name + "_BigO",
- complexity_capture_name + "_RMS", "N");
-
-// ========================================================================= //
-// --------------------------- TEST CASES END ------------------------------ //
-// ========================================================================= //
-
-int main(int argc, char *argv[]) { RunOutputTests(argc, argv); }
+++ /dev/null
-#undef NDEBUG
-#include <cassert>
-#include <cstddef>
-
-#include "benchmark/benchmark.h"
-
-#if __cplusplus >= 201103L
-#error C++11 or greater detected. Should be C++03.
-#endif
-
-#ifdef BENCHMARK_HAS_CXX11
-#error C++11 or greater detected by the library. BENCHMARK_HAS_CXX11 is defined.
-#endif
-
-void BM_empty(benchmark::State& state) {
- while (state.KeepRunning()) {
- volatile benchmark::IterationCount x = state.iterations();
- ((void)x);
- }
-}
-BENCHMARK(BM_empty);
-
-// The new C++11 interface for args/ranges requires initializer list support.
-// Therefore we provide the old interface to support C++03.
-void BM_old_arg_range_interface(benchmark::State& state) {
- assert((state.range(0) == 1 && state.range(1) == 2) ||
- (state.range(0) == 5 && state.range(1) == 6));
- while (state.KeepRunning()) {
- }
-}
-BENCHMARK(BM_old_arg_range_interface)->ArgPair(1, 2)->RangePair(5, 5, 6, 6);
-
-template <class T, class U>
-void BM_template2(benchmark::State& state) {
- BM_empty(state);
-}
-BENCHMARK_TEMPLATE2(BM_template2, int, long);
-
-template <class T>
-void BM_template1(benchmark::State& state) {
- BM_empty(state);
-}
-BENCHMARK_TEMPLATE(BM_template1, long);
-BENCHMARK_TEMPLATE1(BM_template1, int);
-
-template <class T>
-struct BM_Fixture : public ::benchmark::Fixture {
-};
-
-BENCHMARK_TEMPLATE_F(BM_Fixture, BM_template1, long)(benchmark::State& state) {
- BM_empty(state);
-}
-BENCHMARK_TEMPLATE1_F(BM_Fixture, BM_template2, int)(benchmark::State& state) {
- BM_empty(state);
-}
-
-void BM_counters(benchmark::State& state) {
- BM_empty(state);
- state.counters["Foo"] = 2;
-}
-BENCHMARK(BM_counters);
-
-BENCHMARK_MAIN();
+++ /dev/null
-// Testing:
-// State::PauseTiming()
-// State::ResumeTiming()
-// Test that CHECK's within these function diagnose when they are called
-// outside of the KeepRunning() loop.
-//
-// NOTE: Users should NOT include or use src/check.h. This is only done in
-// order to test library internals.
-
-#include <cstdlib>
-#include <stdexcept>
-
-#include "../src/check.h"
-#include "benchmark/benchmark.h"
-
-#if defined(__GNUC__) && !defined(__EXCEPTIONS)
-#define TEST_HAS_NO_EXCEPTIONS
-#endif
-
-void TestHandler() {
-#ifndef TEST_HAS_NO_EXCEPTIONS
- throw std::logic_error("");
-#else
- std::abort();
-#endif
-}
-
-void try_invalid_pause_resume(benchmark::State& state) {
-#if !defined(TEST_BENCHMARK_LIBRARY_HAS_NO_ASSERTIONS) && !defined(TEST_HAS_NO_EXCEPTIONS)
- try {
- state.PauseTiming();
- std::abort();
- } catch (std::logic_error const&) {
- }
- try {
- state.ResumeTiming();
- std::abort();
- } catch (std::logic_error const&) {
- }
-#else
- (void)state; // avoid unused warning
-#endif
-}
-
-void BM_diagnostic_test(benchmark::State& state) {
- static bool called_once = false;
-
- if (called_once == false) try_invalid_pause_resume(state);
-
- for (auto _ : state) {
- benchmark::DoNotOptimize(state.iterations());
- }
-
- if (called_once == false) try_invalid_pause_resume(state);
-
- called_once = true;
-}
-BENCHMARK(BM_diagnostic_test);
-
-
-void BM_diagnostic_test_keep_running(benchmark::State& state) {
- static bool called_once = false;
-
- if (called_once == false) try_invalid_pause_resume(state);
-
- while(state.KeepRunning()) {
- benchmark::DoNotOptimize(state.iterations());
- }
-
- if (called_once == false) try_invalid_pause_resume(state);
-
- called_once = true;
-}
-BENCHMARK(BM_diagnostic_test_keep_running);
-
-int main(int argc, char* argv[]) {
- benchmark::internal::GetAbortHandler() = &TestHandler;
- benchmark::Initialize(&argc, argv);
- benchmark::RunSpecifiedBenchmarks();
-}
+++ /dev/null
-
-#undef NDEBUG
-#include <cstdio>
-#include <string>
-
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-// Ok this test is super ugly. We want to check what happens with the file
-// reporter in the presence of DisplayAggregatesOnly().
-// We do not care about console output, the normal tests check that already.
-
-void BM_SummaryRepeat(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_SummaryRepeat)->Repetitions(3)->DisplayAggregatesOnly();
-
-int main(int argc, char* argv[]) {
- const std::string output = GetFileReporterOutput(argc, argv);
-
- if (SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3") != 6 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3\"") != 3 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_mean\"") != 1 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_median\"") !=
- 1 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"") !=
- 1) {
- std::cout << "Precondition mismatch. Expected to only find 6 "
- "occurrences of \"BM_SummaryRepeat/repeats:3\" substring:\n"
- "\"name\": \"BM_SummaryRepeat/repeats:3\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3_mean\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3_median\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"\nThe entire "
- "output:\n";
- std::cout << output;
- return 1;
- }
-
- return 0;
-}
+++ /dev/null
-#include <benchmark/benchmark.h>
-
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wreturn-type"
-#endif
-
-extern "C" {
-
-extern int ExternInt;
-extern int ExternInt2;
-extern int ExternInt3;
-
-inline int Add42(int x) { return x + 42; }
-
-struct NotTriviallyCopyable {
- NotTriviallyCopyable();
- explicit NotTriviallyCopyable(int x) : value(x) {}
- NotTriviallyCopyable(NotTriviallyCopyable const&);
- int value;
-};
-
-struct Large {
- int value;
- int data[2];
-};
-
-}
-// CHECK-LABEL: test_with_rvalue:
-extern "C" void test_with_rvalue() {
- benchmark::DoNotOptimize(Add42(0));
- // CHECK: movl $42, %eax
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_large_rvalue:
-extern "C" void test_with_large_rvalue() {
- benchmark::DoNotOptimize(Large{ExternInt, {ExternInt, ExternInt}});
- // CHECK: ExternInt(%rip)
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_non_trivial_rvalue:
-extern "C" void test_with_non_trivial_rvalue() {
- benchmark::DoNotOptimize(NotTriviallyCopyable(ExternInt));
- // CHECK: mov{{l|q}} ExternInt(%rip)
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_lvalue:
-extern "C" void test_with_lvalue() {
- int x = 101;
- benchmark::DoNotOptimize(x);
- // CHECK-GNU: movl $101, %eax
- // CHECK-CLANG: movl $101, -{{[0-9]+}}(%[[REG:[a-z]+]])
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_large_lvalue:
-extern "C" void test_with_large_lvalue() {
- Large L{ExternInt, {ExternInt, ExternInt}};
- benchmark::DoNotOptimize(L);
- // CHECK: ExternInt(%rip)
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_non_trivial_lvalue:
-extern "C" void test_with_non_trivial_lvalue() {
- NotTriviallyCopyable NTC(ExternInt);
- benchmark::DoNotOptimize(NTC);
- // CHECK: ExternInt(%rip)
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_const_lvalue:
-extern "C" void test_with_const_lvalue() {
- const int x = 123;
- benchmark::DoNotOptimize(x);
- // CHECK: movl $123, %eax
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_large_const_lvalue:
-extern "C" void test_with_large_const_lvalue() {
- const Large L{ExternInt, {ExternInt, ExternInt}};
- benchmark::DoNotOptimize(L);
- // CHECK: ExternInt(%rip)
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]])
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
- // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]])
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_with_non_trivial_const_lvalue:
-extern "C" void test_with_non_trivial_const_lvalue() {
- const NotTriviallyCopyable Obj(ExternInt);
- benchmark::DoNotOptimize(Obj);
- // CHECK: mov{{q|l}} ExternInt(%rip)
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_div_by_two:
-extern "C" int test_div_by_two(int input) {
- int divisor = 2;
- benchmark::DoNotOptimize(divisor);
- return input / divisor;
- // CHECK: movl $2, [[DEST:.*]]
- // CHECK: idivl [[DEST]]
- // CHECK: ret
-}
-
-// CHECK-LABEL: test_inc_integer:
-extern "C" int test_inc_integer() {
- int x = 0;
- for (int i=0; i < 5; ++i)
- benchmark::DoNotOptimize(++x);
- // CHECK: movl $1, [[DEST:.*]]
- // CHECK: {{(addl \$1,|incl)}} [[DEST]]
- // CHECK: {{(addl \$1,|incl)}} [[DEST]]
- // CHECK: {{(addl \$1,|incl)}} [[DEST]]
- // CHECK: {{(addl \$1,|incl)}} [[DEST]]
- // CHECK-CLANG: movl [[DEST]], %eax
- // CHECK: ret
- return x;
-}
-
-// CHECK-LABEL: test_pointer_rvalue
-extern "C" void test_pointer_rvalue() {
- // CHECK: movl $42, [[DEST:.*]]
- // CHECK: leaq [[DEST]], %rax
- // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]])
- // CHECK: ret
- int x = 42;
- benchmark::DoNotOptimize(&x);
-}
-
-// CHECK-LABEL: test_pointer_const_lvalue:
-extern "C" void test_pointer_const_lvalue() {
- // CHECK: movl $42, [[DEST:.*]]
- // CHECK: leaq [[DEST]], %rax
- // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]])
- // CHECK: ret
- int x = 42;
- int * const xp = &x;
- benchmark::DoNotOptimize(xp);
-}
-
-// CHECK-LABEL: test_pointer_lvalue:
-extern "C" void test_pointer_lvalue() {
- // CHECK: movl $42, [[DEST:.*]]
- // CHECK: leaq [[DEST]], %rax
- // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z+]+]])
- // CHECK: ret
- int x = 42;
- int *xp = &x;
- benchmark::DoNotOptimize(xp);
-}
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-#include <cstdint>
-
-namespace {
-#if defined(__GNUC__)
-std::uint64_t double_up(const std::uint64_t x) __attribute__((const));
-#endif
-std::uint64_t double_up(const std::uint64_t x) { return x * 2; }
-}
-
-// Using DoNotOptimize on types like BitRef seem to cause a lot of problems
-// with the inline assembly on both GCC and Clang.
-struct BitRef {
- int index;
- unsigned char &byte;
-
-public:
- static BitRef Make() {
- static unsigned char arr[2] = {};
- BitRef b(1, arr[0]);
- return b;
- }
-private:
- BitRef(int i, unsigned char& b) : index(i), byte(b) {}
-};
-
-int main(int, char*[]) {
- // this test verifies compilation of DoNotOptimize() for some types
-
- char buffer8[8] = "";
- benchmark::DoNotOptimize(buffer8);
-
- char buffer20[20] = "";
- benchmark::DoNotOptimize(buffer20);
-
- char buffer1024[1024] = "";
- benchmark::DoNotOptimize(buffer1024);
- benchmark::DoNotOptimize(&buffer1024[0]);
-
- int x = 123;
- benchmark::DoNotOptimize(x);
- benchmark::DoNotOptimize(&x);
- benchmark::DoNotOptimize(x += 42);
-
- benchmark::DoNotOptimize(double_up(x));
-
- // These tests are to e
- benchmark::DoNotOptimize(BitRef::Make());
- BitRef lval = BitRef::Make();
- benchmark::DoNotOptimize(lval);
-}
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-#include <cassert>
-#include <cmath>
-#include <cstdint>
-#include <cstdlib>
-
-#include <iostream>
-#include <limits>
-#include <sstream>
-#include <string>
-
-namespace {
-
-class TestReporter : public benchmark::ConsoleReporter {
- public:
- virtual bool ReportContext(const Context& context) {
- return ConsoleReporter::ReportContext(context);
- };
-
- virtual void ReportRuns(const std::vector<Run>& report) {
- ++count_;
- ConsoleReporter::ReportRuns(report);
- };
-
- TestReporter() : count_(0) {}
-
- virtual ~TestReporter() {}
-
- size_t GetCount() const { return count_; }
-
- private:
- mutable size_t count_;
-};
-
-} // end namespace
-
-static void NoPrefix(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(NoPrefix);
-
-static void BM_Foo(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_Foo);
-
-static void BM_Bar(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_Bar);
-
-static void BM_FooBar(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_FooBar);
-
-static void BM_FooBa(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_FooBa);
-
-int main(int argc, char **argv) {
- bool list_only = false;
- for (int i = 0; i < argc; ++i)
- list_only |= std::string(argv[i]).find("--benchmark_list_tests") !=
- std::string::npos;
-
- benchmark::Initialize(&argc, argv);
-
- TestReporter test_reporter;
- const size_t returned_count =
- benchmark::RunSpecifiedBenchmarks(&test_reporter);
-
- if (argc == 2) {
- // Make sure we ran all of the tests
- std::stringstream ss(argv[1]);
- size_t expected_return;
- ss >> expected_return;
-
- if (returned_count != expected_return) {
- std::cerr << "ERROR: Expected " << expected_return
- << " tests to match the filter but returned_count = "
- << returned_count << std::endl;
- return -1;
- }
-
- const size_t expected_reports = list_only ? 0 : expected_return;
- const size_t reports_count = test_reporter.GetCount();
- if (reports_count != expected_reports) {
- std::cerr << "ERROR: Expected " << expected_reports
- << " tests to be run but reported_count = " << reports_count
- << std::endl;
- return -1;
- }
- }
-
- return 0;
-}
+++ /dev/null
-
-#include "benchmark/benchmark.h"
-
-#include <cassert>
-#include <memory>
-
-class MyFixture : public ::benchmark::Fixture {
- public:
- void SetUp(const ::benchmark::State& state) {
- if (state.thread_index == 0) {
- assert(data.get() == nullptr);
- data.reset(new int(42));
- }
- }
-
- void TearDown(const ::benchmark::State& state) {
- if (state.thread_index == 0) {
- assert(data.get() != nullptr);
- data.reset();
- }
- }
-
- ~MyFixture() { assert(data == nullptr); }
-
- std::unique_ptr<int> data;
-};
-
-BENCHMARK_F(MyFixture, Foo)(benchmark::State &st) {
- assert(data.get() != nullptr);
- assert(*data == 42);
- for (auto _ : st) {
- }
-}
-
-BENCHMARK_DEFINE_F(MyFixture, Bar)(benchmark::State& st) {
- if (st.thread_index == 0) {
- assert(data.get() != nullptr);
- assert(*data == 42);
- }
- for (auto _ : st) {
- assert(data.get() != nullptr);
- assert(*data == 42);
- }
- st.SetItemsProcessed(st.range(0));
-}
-BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42);
-BENCHMARK_REGISTER_F(MyFixture, Bar)->Arg(42)->ThreadPerCpu();
-
-BENCHMARK_MAIN();
+++ /dev/null
-
-#undef NDEBUG
-
-#include <chrono>
-#include <thread>
-#include "../src/timers.h"
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-static const std::chrono::duration<double, std::milli> time_frame(50);
-static const double time_frame_in_sec(
- std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1, 1>>>(
- time_frame)
- .count());
-
-void MyBusySpinwait() {
- const auto start = benchmark::ChronoClockNow();
-
- while (true) {
- const auto now = benchmark::ChronoClockNow();
- const auto elapsed = now - start;
-
- if (std::chrono::duration<double, std::chrono::seconds::period>(elapsed) >=
- time_frame)
- return;
- }
-}
-
-// ========================================================================= //
-// --------------------------- TEST CASES BEGIN ---------------------------- //
-// ========================================================================= //
-
-// ========================================================================= //
-// BM_MainThread
-
-void BM_MainThread(benchmark::State& state) {
- for (auto _ : state) {
- MyBusySpinwait();
- state.SetIterationTime(time_frame_in_sec);
- }
- state.counters["invtime"] =
- benchmark::Counter{1, benchmark::Counter::kIsRate};
-}
-
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1);
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1)->UseRealTime();
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1)->UseManualTime();
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(1)->MeasureProcessCPUTime();
-BENCHMARK(BM_MainThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime()
- ->UseRealTime();
-BENCHMARK(BM_MainThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime()
- ->UseManualTime();
-
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2);
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2)->UseRealTime();
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2)->UseManualTime();
-BENCHMARK(BM_MainThread)->Iterations(1)->Threads(2)->MeasureProcessCPUTime();
-BENCHMARK(BM_MainThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime()
- ->UseRealTime();
-BENCHMARK(BM_MainThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime()
- ->UseManualTime();
-
-// ========================================================================= //
-// BM_WorkerThread
-
-void BM_WorkerThread(benchmark::State& state) {
- for (auto _ : state) {
- std::thread Worker(&MyBusySpinwait);
- Worker.join();
- state.SetIterationTime(time_frame_in_sec);
- }
- state.counters["invtime"] =
- benchmark::Counter{1, benchmark::Counter::kIsRate};
-}
-
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1);
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1)->UseRealTime();
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1)->UseManualTime();
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(1)->MeasureProcessCPUTime();
-BENCHMARK(BM_WorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime()
- ->UseRealTime();
-BENCHMARK(BM_WorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime()
- ->UseManualTime();
-
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2);
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2)->UseRealTime();
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2)->UseManualTime();
-BENCHMARK(BM_WorkerThread)->Iterations(1)->Threads(2)->MeasureProcessCPUTime();
-BENCHMARK(BM_WorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime()
- ->UseRealTime();
-BENCHMARK(BM_WorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime()
- ->UseManualTime();
-
-// ========================================================================= //
-// BM_MainThreadAndWorkerThread
-
-void BM_MainThreadAndWorkerThread(benchmark::State& state) {
- for (auto _ : state) {
- std::thread Worker(&MyBusySpinwait);
- MyBusySpinwait();
- Worker.join();
- state.SetIterationTime(time_frame_in_sec);
- }
- state.counters["invtime"] =
- benchmark::Counter{1, benchmark::Counter::kIsRate};
-}
-
-BENCHMARK(BM_MainThreadAndWorkerThread)->Iterations(1)->Threads(1);
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->UseRealTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->UseManualTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime()
- ->UseRealTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(1)
- ->MeasureProcessCPUTime()
- ->UseManualTime();
-
-BENCHMARK(BM_MainThreadAndWorkerThread)->Iterations(1)->Threads(2);
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->UseRealTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->UseManualTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime()
- ->UseRealTime();
-BENCHMARK(BM_MainThreadAndWorkerThread)
- ->Iterations(1)
- ->Threads(2)
- ->MeasureProcessCPUTime()
- ->UseManualTime();
-
-// ========================================================================= //
-// ---------------------------- TEST CASES END ----------------------------- //
-// ========================================================================= //
-
-int main(int argc, char* argv[]) { RunOutputTests(argc, argv); }
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-void BM_empty(benchmark::State& state) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(state.iterations());
- }
-}
-BENCHMARK(BM_empty);
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-#include <cstdlib>
-#include <map>
-
-namespace {
-
-std::map<int, int> ConstructRandomMap(int size) {
- std::map<int, int> m;
- for (int i = 0; i < size; ++i) {
- m.insert(std::make_pair(std::rand() % size, std::rand() % size));
- }
- return m;
-}
-
-} // namespace
-
-// Basic version.
-static void BM_MapLookup(benchmark::State& state) {
- const int size = static_cast<int>(state.range(0));
- std::map<int, int> m;
- for (auto _ : state) {
- state.PauseTiming();
- m = ConstructRandomMap(size);
- state.ResumeTiming();
- for (int i = 0; i < size; ++i) {
- benchmark::DoNotOptimize(m.find(std::rand() % size));
- }
- }
- state.SetItemsProcessed(state.iterations() * size);
-}
-BENCHMARK(BM_MapLookup)->Range(1 << 3, 1 << 12);
-
-// Using fixtures.
-class MapFixture : public ::benchmark::Fixture {
- public:
- void SetUp(const ::benchmark::State& st) {
- m = ConstructRandomMap(static_cast<int>(st.range(0)));
- }
-
- void TearDown(const ::benchmark::State&) { m.clear(); }
-
- std::map<int, int> m;
-};
-
-BENCHMARK_DEFINE_F(MapFixture, Lookup)(benchmark::State& state) {
- const int size = static_cast<int>(state.range(0));
- for (auto _ : state) {
- for (int i = 0; i < size; ++i) {
- benchmark::DoNotOptimize(m.find(std::rand() % size));
- }
- }
- state.SetItemsProcessed(state.iterations() * size);
-}
-BENCHMARK_REGISTER_F(MapFixture, Lookup)->Range(1 << 3, 1 << 12);
-
-BENCHMARK_MAIN();
+++ /dev/null
-#include <memory>
-
-#include "../src/check.h"
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-class TestMemoryManager : public benchmark::MemoryManager {
- void Start() {}
- void Stop(Result* result) {
- result->num_allocs = 42;
- result->max_bytes_used = 42000;
- }
-};
-
-void BM_empty(benchmark::State& state) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(state.iterations());
- }
-}
-BENCHMARK(BM_empty);
-
-ADD_CASES(TC_ConsoleOut, {{"^BM_empty %console_report$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_empty\",$"},
- {"\"run_name\": \"BM_empty\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"allocs_per_iter\": %float,$", MR_Next},
- {"\"max_bytes_used\": 42000$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_empty\",%csv_report$"}});
-
-int main(int argc, char* argv[]) {
- std::unique_ptr<benchmark::MemoryManager> mm(new TestMemoryManager());
-
- benchmark::RegisterMemoryManager(mm.get());
- RunOutputTests(argc, argv);
- benchmark::RegisterMemoryManager(nullptr);
-}
+++ /dev/null
-#include "benchmark/benchmark.h"
-
-#include <cassert>
-#include <iostream>
-#include <set>
-#include <vector>
-
-class MultipleRangesFixture : public ::benchmark::Fixture {
- public:
- MultipleRangesFixture()
- : expectedValues({{1, 3, 5},
- {1, 3, 8},
- {1, 3, 15},
- {2, 3, 5},
- {2, 3, 8},
- {2, 3, 15},
- {1, 4, 5},
- {1, 4, 8},
- {1, 4, 15},
- {2, 4, 5},
- {2, 4, 8},
- {2, 4, 15},
- {1, 7, 5},
- {1, 7, 8},
- {1, 7, 15},
- {2, 7, 5},
- {2, 7, 8},
- {2, 7, 15},
- {7, 6, 3}}) {}
-
- void SetUp(const ::benchmark::State& state) {
- std::vector<int64_t> ranges = {state.range(0), state.range(1),
- state.range(2)};
-
- assert(expectedValues.find(ranges) != expectedValues.end());
-
- actualValues.insert(ranges);
- }
-
- // NOTE: This is not TearDown as we want to check after _all_ runs are
- // complete.
- virtual ~MultipleRangesFixture() {
- if (actualValues != expectedValues) {
- std::cout << "EXPECTED\n";
- for (auto v : expectedValues) {
- std::cout << "{";
- for (int64_t iv : v) {
- std::cout << iv << ", ";
- }
- std::cout << "}\n";
- }
- std::cout << "ACTUAL\n";
- for (auto v : actualValues) {
- std::cout << "{";
- for (int64_t iv : v) {
- std::cout << iv << ", ";
- }
- std::cout << "}\n";
- }
- }
- }
-
- std::set<std::vector<int64_t>> expectedValues;
- std::set<std::vector<int64_t>> actualValues;
-};
-
-BENCHMARK_DEFINE_F(MultipleRangesFixture, Empty)(benchmark::State& state) {
- for (auto _ : state) {
- int64_t product = state.range(0) * state.range(1) * state.range(2);
- for (int64_t x = 0; x < product; x++) {
- benchmark::DoNotOptimize(x);
- }
- }
-}
-
-BENCHMARK_REGISTER_F(MultipleRangesFixture, Empty)
- ->RangeMultiplier(2)
- ->Ranges({{1, 2}, {3, 7}, {5, 15}})
- ->Args({7, 6, 3});
-
-void BM_CheckDefaultArgument(benchmark::State& state) {
- // Test that the 'range()' without an argument is the same as 'range(0)'.
- assert(state.range() == state.range(0));
- assert(state.range() != state.range(1));
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_CheckDefaultArgument)->Ranges({{1, 5}, {6, 10}});
-
-static void BM_MultipleRanges(benchmark::State& st) {
- for (auto _ : st) {
- }
-}
-BENCHMARK(BM_MultipleRanges)->Ranges({{5, 5}, {6, 6}});
-
-BENCHMARK_MAIN();
+++ /dev/null
-#include "benchmark/benchmark.h"
-#include <chrono>
-#include <thread>
-
-#if defined(NDEBUG)
-#undef NDEBUG
-#endif
-#include <cassert>
-
-void BM_basic(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-
-void BM_basic_slow(benchmark::State& state) {
- std::chrono::milliseconds sleep_duration(state.range(0));
- for (auto _ : state) {
- std::this_thread::sleep_for(
- std::chrono::duration_cast<std::chrono::nanoseconds>(sleep_duration));
- }
-}
-
-BENCHMARK(BM_basic);
-BENCHMARK(BM_basic)->Arg(42);
-BENCHMARK(BM_basic_slow)->Arg(10)->Unit(benchmark::kNanosecond);
-BENCHMARK(BM_basic_slow)->Arg(100)->Unit(benchmark::kMicrosecond);
-BENCHMARK(BM_basic_slow)->Arg(1000)->Unit(benchmark::kMillisecond);
-BENCHMARK(BM_basic)->Range(1, 8);
-BENCHMARK(BM_basic)->RangeMultiplier(2)->Range(1, 8);
-BENCHMARK(BM_basic)->DenseRange(10, 15);
-BENCHMARK(BM_basic)->Args({42, 42});
-BENCHMARK(BM_basic)->Ranges({{64, 512}, {64, 512}});
-BENCHMARK(BM_basic)->MinTime(0.7);
-BENCHMARK(BM_basic)->UseRealTime();
-BENCHMARK(BM_basic)->ThreadRange(2, 4);
-BENCHMARK(BM_basic)->ThreadPerCpu();
-BENCHMARK(BM_basic)->Repetitions(3);
-BENCHMARK(BM_basic)
- ->RangeMultiplier(std::numeric_limits<int>::max())
- ->Range(std::numeric_limits<int64_t>::min(),
- std::numeric_limits<int64_t>::max());
-
-// Negative ranges
-BENCHMARK(BM_basic)->Range(-64, -1);
-BENCHMARK(BM_basic)->RangeMultiplier(4)->Range(-8, 8);
-BENCHMARK(BM_basic)->DenseRange(-2, 2, 1);
-BENCHMARK(BM_basic)->Ranges({{-64, 1}, {-8, -1}});
-
-void CustomArgs(benchmark::internal::Benchmark* b) {
- for (int i = 0; i < 10; ++i) {
- b->Arg(i);
- }
-}
-
-BENCHMARK(BM_basic)->Apply(CustomArgs);
-
-void BM_explicit_iteration_count(benchmark::State& state) {
- // Test that benchmarks specified with an explicit iteration count are
- // only run once.
- static bool invoked_before = false;
- assert(!invoked_before);
- invoked_before = true;
-
- // Test that the requested iteration count is respected.
- assert(state.max_iterations == 42);
- size_t actual_iterations = 0;
- for (auto _ : state)
- ++actual_iterations;
- assert(state.iterations() == state.max_iterations);
- assert(state.iterations() == 42);
-
-}
-BENCHMARK(BM_explicit_iteration_count)->Iterations(42);
-
-BENCHMARK_MAIN();
+++ /dev/null
-#ifndef TEST_OUTPUT_TEST_H
-#define TEST_OUTPUT_TEST_H
-
-#undef NDEBUG
-#include <functional>
-#include <initializer_list>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "../src/re.h"
-#include "benchmark/benchmark.h"
-
-#define CONCAT2(x, y) x##y
-#define CONCAT(x, y) CONCAT2(x, y)
-
-#define ADD_CASES(...) int CONCAT(dummy, __LINE__) = ::AddCases(__VA_ARGS__)
-
-#define SET_SUBSTITUTIONS(...) \
- int CONCAT(dummy, __LINE__) = ::SetSubstitutions(__VA_ARGS__)
-
-enum MatchRules {
- MR_Default, // Skip non-matching lines until a match is found.
- MR_Next, // Match must occur on the next line.
- MR_Not // No line between the current position and the next match matches
- // the regex
-};
-
-struct TestCase {
- TestCase(std::string re, int rule = MR_Default);
-
- std::string regex_str;
- int match_rule;
- std::string substituted_regex;
- std::shared_ptr<benchmark::Regex> regex;
-};
-
-enum TestCaseID {
- TC_ConsoleOut,
- TC_ConsoleErr,
- TC_JSONOut,
- TC_JSONErr,
- TC_CSVOut,
- TC_CSVErr,
-
- TC_NumID // PRIVATE
-};
-
-// Add a list of test cases to be run against the output specified by
-// 'ID'
-int AddCases(TestCaseID ID, std::initializer_list<TestCase> il);
-
-// Add or set a list of substitutions to be performed on constructed regex's
-// See 'output_test_helper.cc' for a list of default substitutions.
-int SetSubstitutions(
- std::initializer_list<std::pair<std::string, std::string>> il);
-
-// Run all output tests.
-void RunOutputTests(int argc, char* argv[]);
-
-// Count the number of 'pat' substrings in the 'haystack' string.
-int SubstrCnt(const std::string& haystack, const std::string& pat);
-
-// Run registered benchmarks with file reporter enabled, and return the content
-// outputted by the file reporter.
-std::string GetFileReporterOutput(int argc, char* argv[]);
-
-// ========================================================================= //
-// ------------------------- Results checking ------------------------------ //
-// ========================================================================= //
-
-// Call this macro to register a benchmark for checking its results. This
-// should be all that's needed. It subscribes a function to check the (CSV)
-// results of a benchmark. This is done only after verifying that the output
-// strings are really as expected.
-// bm_name_pattern: a name or a regex pattern which will be matched against
-// all the benchmark names. Matching benchmarks
-// will be the subject of a call to checker_function
-// checker_function: should be of type ResultsCheckFn (see below)
-#define CHECK_BENCHMARK_RESULTS(bm_name_pattern, checker_function) \
- size_t CONCAT(dummy, __LINE__) = AddChecker(bm_name_pattern, checker_function)
-
-struct Results;
-typedef std::function<void(Results const&)> ResultsCheckFn;
-
-size_t AddChecker(const char* bm_name_pattern, ResultsCheckFn fn);
-
-// Class holding the results of a benchmark.
-// It is passed in calls to checker functions.
-struct Results {
- // the benchmark name
- std::string name;
- // the benchmark fields
- std::map<std::string, std::string> values;
-
- Results(const std::string& n) : name(n) {}
-
- int NumThreads() const;
-
- double NumIterations() const;
-
- typedef enum { kCpuTime, kRealTime } BenchmarkTime;
-
- // get cpu_time or real_time in seconds
- double GetTime(BenchmarkTime which) const;
-
- // get the real_time duration of the benchmark in seconds.
- // it is better to use fuzzy float checks for this, as the float
- // ASCII formatting is lossy.
- double DurationRealTime() const {
- return NumIterations() * GetTime(kRealTime);
- }
- // get the cpu_time duration of the benchmark in seconds
- double DurationCPUTime() const {
- return NumIterations() * GetTime(kCpuTime);
- }
-
- // get the string for a result by name, or nullptr if the name
- // is not found
- const std::string* Get(const char* entry_name) const {
- auto it = values.find(entry_name);
- if (it == values.end()) return nullptr;
- return &it->second;
- }
-
- // get a result by name, parsed as a specific type.
- // NOTE: for counters, use GetCounterAs instead.
- template <class T>
- T GetAs(const char* entry_name) const;
-
- // counters are written as doubles, so they have to be read first
- // as a double, and only then converted to the asked type.
- template <class T>
- T GetCounterAs(const char* entry_name) const {
- double dval = GetAs<double>(entry_name);
- T tval = static_cast<T>(dval);
- return tval;
- }
-};
-
-template <class T>
-T Results::GetAs(const char* entry_name) const {
- auto* sv = Get(entry_name);
- CHECK(sv != nullptr && !sv->empty());
- std::stringstream ss;
- ss << *sv;
- T out;
- ss >> out;
- CHECK(!ss.fail());
- return out;
-}
-
-//----------------------------------
-// Macros to help in result checking. Do not use them with arguments causing
-// side-effects.
-
-// clang-format off
-
-#define _CHECK_RESULT_VALUE(entry, getfn, var_type, var_name, relationship, value) \
- CONCAT(CHECK_, relationship) \
- (entry.getfn< var_type >(var_name), (value)) << "\n" \
- << __FILE__ << ":" << __LINE__ << ": " << (entry).name << ":\n" \
- << __FILE__ << ":" << __LINE__ << ": " \
- << "expected (" << #var_type << ")" << (var_name) \
- << "=" << (entry).getfn< var_type >(var_name) \
- << " to be " #relationship " to " << (value) << "\n"
-
-// check with tolerance. eps_factor is the tolerance window, which is
-// interpreted relative to value (eg, 0.1 means 10% of value).
-#define _CHECK_FLOAT_RESULT_VALUE(entry, getfn, var_type, var_name, relationship, value, eps_factor) \
- CONCAT(CHECK_FLOAT_, relationship) \
- (entry.getfn< var_type >(var_name), (value), (eps_factor) * (value)) << "\n" \
- << __FILE__ << ":" << __LINE__ << ": " << (entry).name << ":\n" \
- << __FILE__ << ":" << __LINE__ << ": " \
- << "expected (" << #var_type << ")" << (var_name) \
- << "=" << (entry).getfn< var_type >(var_name) \
- << " to be " #relationship " to " << (value) << "\n" \
- << __FILE__ << ":" << __LINE__ << ": " \
- << "with tolerance of " << (eps_factor) * (value) \
- << " (" << (eps_factor)*100. << "%), " \
- << "but delta was " << ((entry).getfn< var_type >(var_name) - (value)) \
- << " (" << (((entry).getfn< var_type >(var_name) - (value)) \
- / \
- ((value) > 1.e-5 || value < -1.e-5 ? value : 1.e-5)*100.) \
- << "%)"
-
-#define CHECK_RESULT_VALUE(entry, var_type, var_name, relationship, value) \
- _CHECK_RESULT_VALUE(entry, GetAs, var_type, var_name, relationship, value)
-
-#define CHECK_COUNTER_VALUE(entry, var_type, var_name, relationship, value) \
- _CHECK_RESULT_VALUE(entry, GetCounterAs, var_type, var_name, relationship, value)
-
-#define CHECK_FLOAT_RESULT_VALUE(entry, var_name, relationship, value, eps_factor) \
- _CHECK_FLOAT_RESULT_VALUE(entry, GetAs, double, var_name, relationship, value, eps_factor)
-
-#define CHECK_FLOAT_COUNTER_VALUE(entry, var_name, relationship, value, eps_factor) \
- _CHECK_FLOAT_RESULT_VALUE(entry, GetCounterAs, double, var_name, relationship, value, eps_factor)
-
-// clang-format on
-
-// ========================================================================= //
-// --------------------------- Misc Utilities ------------------------------ //
-// ========================================================================= //
-
-namespace {
-
-const char* const dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
-
-} // end namespace
-
-#endif // TEST_OUTPUT_TEST_H
+++ /dev/null
-#include <cstdio>
-#include <cstring>
-#include <fstream>
-#include <iostream>
-#include <map>
-#include <memory>
-#include <random>
-#include <sstream>
-#include <streambuf>
-
-#include "../src/benchmark_api_internal.h"
-#include "../src/check.h" // NOTE: check.h is for internal use only!
-#include "../src/re.h" // NOTE: re.h is for internal use only
-#include "output_test.h"
-
-// ========================================================================= //
-// ------------------------------ Internals -------------------------------- //
-// ========================================================================= //
-namespace internal {
-namespace {
-
-using TestCaseList = std::vector<TestCase>;
-
-// Use a vector because the order elements are added matters during iteration.
-// std::map/unordered_map don't guarantee that.
-// For example:
-// SetSubstitutions({{"%HelloWorld", "Hello"}, {"%Hello", "Hi"}});
-// Substitute("%HelloWorld") // Always expands to Hello.
-using SubMap = std::vector<std::pair<std::string, std::string>>;
-
-TestCaseList& GetTestCaseList(TestCaseID ID) {
- // Uses function-local statics to ensure initialization occurs
- // before first use.
- static TestCaseList lists[TC_NumID];
- return lists[ID];
-}
-
-SubMap& GetSubstitutions() {
- // Don't use 'dec_re' from header because it may not yet be initialized.
- // clang-format off
- static std::string safe_dec_re = "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?";
- static std::string time_re = "([0-9]+[.])?[0-9]+";
- static SubMap map = {
- {"%float", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"},
- // human-readable float
- {"%hrfloat", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?[kMGTPEZYmunpfazy]?"},
- {"%int", "[ ]*[0-9]+"},
- {" %s ", "[ ]+"},
- {"%time", "[ ]*" + time_re + "[ ]+ns"},
- {"%console_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns [ ]*[0-9]+"},
- {"%console_time_only_report", "[ ]*" + time_re + "[ ]+ns [ ]*" + time_re + "[ ]+ns"},
- {"%console_us_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us [ ]*[0-9]+"},
- {"%console_us_time_only_report", "[ ]*" + time_re + "[ ]+us [ ]*" + time_re + "[ ]+us"},
- {"%csv_header",
- "name,iterations,real_time,cpu_time,time_unit,bytes_per_second,"
- "items_per_second,label,error_occurred,error_message"},
- {"%csv_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns,,,,,"},
- {"%csv_us_report", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",us,,,,,"},
- {"%csv_bytes_report",
- "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns," + safe_dec_re + ",,,,"},
- {"%csv_items_report",
- "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns,," + safe_dec_re + ",,,"},
- {"%csv_bytes_items_report",
- "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns," + safe_dec_re +
- "," + safe_dec_re + ",,,"},
- {"%csv_label_report_begin", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns,,,"},
- {"%csv_label_report_end", ",,"}};
- // clang-format on
- return map;
-}
-
-std::string PerformSubstitutions(std::string source) {
- SubMap const& subs = GetSubstitutions();
- using SizeT = std::string::size_type;
- for (auto const& KV : subs) {
- SizeT pos;
- SizeT next_start = 0;
- while ((pos = source.find(KV.first, next_start)) != std::string::npos) {
- next_start = pos + KV.second.size();
- source.replace(pos, KV.first.size(), KV.second);
- }
- }
- return source;
-}
-
-void CheckCase(std::stringstream& remaining_output, TestCase const& TC,
- TestCaseList const& not_checks) {
- std::string first_line;
- bool on_first = true;
- std::string line;
- while (remaining_output.eof() == false) {
- CHECK(remaining_output.good());
- std::getline(remaining_output, line);
- if (on_first) {
- first_line = line;
- on_first = false;
- }
- for (const auto& NC : not_checks) {
- CHECK(!NC.regex->Match(line))
- << "Unexpected match for line \"" << line << "\" for MR_Not regex \""
- << NC.regex_str << "\""
- << "\n actual regex string \"" << TC.substituted_regex << "\""
- << "\n started matching near: " << first_line;
- }
- if (TC.regex->Match(line)) return;
- CHECK(TC.match_rule != MR_Next)
- << "Expected line \"" << line << "\" to match regex \"" << TC.regex_str
- << "\""
- << "\n actual regex string \"" << TC.substituted_regex << "\""
- << "\n started matching near: " << first_line;
- }
- CHECK(remaining_output.eof() == false)
- << "End of output reached before match for regex \"" << TC.regex_str
- << "\" was found"
- << "\n actual regex string \"" << TC.substituted_regex << "\""
- << "\n started matching near: " << first_line;
-}
-
-void CheckCases(TestCaseList const& checks, std::stringstream& output) {
- std::vector<TestCase> not_checks;
- for (size_t i = 0; i < checks.size(); ++i) {
- const auto& TC = checks[i];
- if (TC.match_rule == MR_Not) {
- not_checks.push_back(TC);
- continue;
- }
- CheckCase(output, TC, not_checks);
- not_checks.clear();
- }
-}
-
-class TestReporter : public benchmark::BenchmarkReporter {
- public:
- TestReporter(std::vector<benchmark::BenchmarkReporter*> reps)
- : reporters_(reps) {}
-
- virtual bool ReportContext(const Context& context) {
- bool last_ret = false;
- bool first = true;
- for (auto rep : reporters_) {
- bool new_ret = rep->ReportContext(context);
- CHECK(first || new_ret == last_ret)
- << "Reports return different values for ReportContext";
- first = false;
- last_ret = new_ret;
- }
- (void)first;
- return last_ret;
- }
-
- void ReportRuns(const std::vector<Run>& report) {
- for (auto rep : reporters_) rep->ReportRuns(report);
- }
- void Finalize() {
- for (auto rep : reporters_) rep->Finalize();
- }
-
- private:
- std::vector<benchmark::BenchmarkReporter*> reporters_;
-};
-} // namespace
-
-} // end namespace internal
-
-// ========================================================================= //
-// -------------------------- Results checking ----------------------------- //
-// ========================================================================= //
-
-namespace internal {
-
-// Utility class to manage subscribers for checking benchmark results.
-// It works by parsing the CSV output to read the results.
-class ResultsChecker {
- public:
- struct PatternAndFn : public TestCase { // reusing TestCase for its regexes
- PatternAndFn(const std::string& rx, ResultsCheckFn fn_)
- : TestCase(rx), fn(fn_) {}
- ResultsCheckFn fn;
- };
-
- std::vector<PatternAndFn> check_patterns;
- std::vector<Results> results;
- std::vector<std::string> field_names;
-
- void Add(const std::string& entry_pattern, ResultsCheckFn fn);
-
- void CheckResults(std::stringstream& output);
-
- private:
- void SetHeader_(const std::string& csv_header);
- void SetValues_(const std::string& entry_csv_line);
-
- std::vector<std::string> SplitCsv_(const std::string& line);
-};
-
-// store the static ResultsChecker in a function to prevent initialization
-// order problems
-ResultsChecker& GetResultsChecker() {
- static ResultsChecker rc;
- return rc;
-}
-
-// add a results checker for a benchmark
-void ResultsChecker::Add(const std::string& entry_pattern, ResultsCheckFn fn) {
- check_patterns.emplace_back(entry_pattern, fn);
-}
-
-// check the results of all subscribed benchmarks
-void ResultsChecker::CheckResults(std::stringstream& output) {
- // first reset the stream to the start
- {
- auto start = std::stringstream::pos_type(0);
- // clear before calling tellg()
- output.clear();
- // seek to zero only when needed
- if (output.tellg() > start) output.seekg(start);
- // and just in case
- output.clear();
- }
- // now go over every line and publish it to the ResultsChecker
- std::string line;
- bool on_first = true;
- while (output.eof() == false) {
- CHECK(output.good());
- std::getline(output, line);
- if (on_first) {
- SetHeader_(line); // this is important
- on_first = false;
- continue;
- }
- SetValues_(line);
- }
- // finally we can call the subscribed check functions
- for (const auto& p : check_patterns) {
- VLOG(2) << "--------------------------------\n";
- VLOG(2) << "checking for benchmarks matching " << p.regex_str << "...\n";
- for (const auto& r : results) {
- if (!p.regex->Match(r.name)) {
- VLOG(2) << p.regex_str << " is not matched by " << r.name << "\n";
- continue;
- } else {
- VLOG(2) << p.regex_str << " is matched by " << r.name << "\n";
- }
- VLOG(1) << "Checking results of " << r.name << ": ... \n";
- p.fn(r);
- VLOG(1) << "Checking results of " << r.name << ": OK.\n";
- }
- }
-}
-
-// prepare for the names in this header
-void ResultsChecker::SetHeader_(const std::string& csv_header) {
- field_names = SplitCsv_(csv_header);
-}
-
-// set the values for a benchmark
-void ResultsChecker::SetValues_(const std::string& entry_csv_line) {
- if (entry_csv_line.empty()) return; // some lines are empty
- CHECK(!field_names.empty());
- auto vals = SplitCsv_(entry_csv_line);
- CHECK_EQ(vals.size(), field_names.size());
- results.emplace_back(vals[0]); // vals[0] is the benchmark name
- auto& entry = results.back();
- for (size_t i = 1, e = vals.size(); i < e; ++i) {
- entry.values[field_names[i]] = vals[i];
- }
-}
-
-// a quick'n'dirty csv splitter (eliminating quotes)
-std::vector<std::string> ResultsChecker::SplitCsv_(const std::string& line) {
- std::vector<std::string> out;
- if (line.empty()) return out;
- if (!field_names.empty()) out.reserve(field_names.size());
- size_t prev = 0, pos = line.find_first_of(','), curr = pos;
- while (pos != line.npos) {
- CHECK(curr > 0);
- if (line[prev] == '"') ++prev;
- if (line[curr - 1] == '"') --curr;
- out.push_back(line.substr(prev, curr - prev));
- prev = pos + 1;
- pos = line.find_first_of(',', pos + 1);
- curr = pos;
- }
- curr = line.size();
- if (line[prev] == '"') ++prev;
- if (line[curr - 1] == '"') --curr;
- out.push_back(line.substr(prev, curr - prev));
- return out;
-}
-
-} // end namespace internal
-
-size_t AddChecker(const char* bm_name, ResultsCheckFn fn) {
- auto& rc = internal::GetResultsChecker();
- rc.Add(bm_name, fn);
- return rc.results.size();
-}
-
-int Results::NumThreads() const {
- auto pos = name.find("/threads:");
- if (pos == name.npos) return 1;
- auto end = name.find('/', pos + 9);
- std::stringstream ss;
- ss << name.substr(pos + 9, end);
- int num = 1;
- ss >> num;
- CHECK(!ss.fail());
- return num;
-}
-
-double Results::NumIterations() const {
- return GetAs<double>("iterations");
-}
-
-double Results::GetTime(BenchmarkTime which) const {
- CHECK(which == kCpuTime || which == kRealTime);
- const char* which_str = which == kCpuTime ? "cpu_time" : "real_time";
- double val = GetAs<double>(which_str);
- auto unit = Get("time_unit");
- CHECK(unit);
- if (*unit == "ns") {
- return val * 1.e-9;
- } else if (*unit == "us") {
- return val * 1.e-6;
- } else if (*unit == "ms") {
- return val * 1.e-3;
- } else if (*unit == "s") {
- return val;
- } else {
- CHECK(1 == 0) << "unknown time unit: " << *unit;
- return 0;
- }
-}
-
-// ========================================================================= //
-// -------------------------- Public API Definitions------------------------ //
-// ========================================================================= //
-
-TestCase::TestCase(std::string re, int rule)
- : regex_str(std::move(re)),
- match_rule(rule),
- substituted_regex(internal::PerformSubstitutions(regex_str)),
- regex(std::make_shared<benchmark::Regex>()) {
- std::string err_str;
- regex->Init(substituted_regex, &err_str);
- CHECK(err_str.empty()) << "Could not construct regex \"" << substituted_regex
- << "\""
- << "\n originally \"" << regex_str << "\""
- << "\n got error: " << err_str;
-}
-
-int AddCases(TestCaseID ID, std::initializer_list<TestCase> il) {
- auto& L = internal::GetTestCaseList(ID);
- L.insert(L.end(), il);
- return 0;
-}
-
-int SetSubstitutions(
- std::initializer_list<std::pair<std::string, std::string>> il) {
- auto& subs = internal::GetSubstitutions();
- for (auto KV : il) {
- bool exists = false;
- KV.second = internal::PerformSubstitutions(KV.second);
- for (auto& EKV : subs) {
- if (EKV.first == KV.first) {
- EKV.second = std::move(KV.second);
- exists = true;
- break;
- }
- }
- if (!exists) subs.push_back(std::move(KV));
- }
- return 0;
-}
-
-// Disable deprecated warnings temporarily because we need to reference
-// CSVReporter but don't want to trigger -Werror=-Wdeprecated-declarations
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-#endif
-void RunOutputTests(int argc, char* argv[]) {
- using internal::GetTestCaseList;
- benchmark::Initialize(&argc, argv);
- auto options = benchmark::internal::GetOutputOptions(/*force_no_color*/ true);
- benchmark::ConsoleReporter CR(options);
- benchmark::JSONReporter JR;
- benchmark::CSVReporter CSVR;
- struct ReporterTest {
- const char* name;
- std::vector<TestCase>& output_cases;
- std::vector<TestCase>& error_cases;
- benchmark::BenchmarkReporter& reporter;
- std::stringstream out_stream;
- std::stringstream err_stream;
-
- ReporterTest(const char* n, std::vector<TestCase>& out_tc,
- std::vector<TestCase>& err_tc,
- benchmark::BenchmarkReporter& br)
- : name(n), output_cases(out_tc), error_cases(err_tc), reporter(br) {
- reporter.SetOutputStream(&out_stream);
- reporter.SetErrorStream(&err_stream);
- }
- } TestCases[] = {
- {"ConsoleReporter", GetTestCaseList(TC_ConsoleOut),
- GetTestCaseList(TC_ConsoleErr), CR},
- {"JSONReporter", GetTestCaseList(TC_JSONOut), GetTestCaseList(TC_JSONErr),
- JR},
- {"CSVReporter", GetTestCaseList(TC_CSVOut), GetTestCaseList(TC_CSVErr),
- CSVR},
- };
-
- // Create the test reporter and run the benchmarks.
- std::cout << "Running benchmarks...\n";
- internal::TestReporter test_rep({&CR, &JR, &CSVR});
- benchmark::RunSpecifiedBenchmarks(&test_rep);
-
- for (auto& rep_test : TestCases) {
- std::string msg = std::string("\nTesting ") + rep_test.name + " Output\n";
- std::string banner(msg.size() - 1, '-');
- std::cout << banner << msg << banner << "\n";
-
- std::cerr << rep_test.err_stream.str();
- std::cout << rep_test.out_stream.str();
-
- internal::CheckCases(rep_test.error_cases, rep_test.err_stream);
- internal::CheckCases(rep_test.output_cases, rep_test.out_stream);
-
- std::cout << "\n";
- }
-
- // now that we know the output is as expected, we can dispatch
- // the checks to subscribees.
- auto& csv = TestCases[2];
- // would use == but gcc spits a warning
- CHECK(std::strcmp(csv.name, "CSVReporter") == 0);
- internal::GetResultsChecker().CheckResults(csv.out_stream);
-}
-
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-int SubstrCnt(const std::string& haystack, const std::string& pat) {
- if (pat.length() == 0) return 0;
- int count = 0;
- for (size_t offset = haystack.find(pat); offset != std::string::npos;
- offset = haystack.find(pat, offset + pat.length()))
- ++count;
- return count;
-}
-
-static char ToHex(int ch) {
- return ch < 10 ? static_cast<char>('0' + ch)
- : static_cast<char>('a' + (ch - 10));
-}
-
-static char RandomHexChar() {
- static std::mt19937 rd{std::random_device{}()};
- static std::uniform_int_distribution<int> mrand{0, 15};
- return ToHex(mrand(rd));
-}
-
-static std::string GetRandomFileName() {
- std::string model = "test.%%%%%%";
- for (auto & ch : model) {
- if (ch == '%')
- ch = RandomHexChar();
- }
- return model;
-}
-
-static bool FileExists(std::string const& name) {
- std::ifstream in(name.c_str());
- return in.good();
-}
-
-static std::string GetTempFileName() {
- // This function attempts to avoid race conditions where two tests
- // create the same file at the same time. However, it still introduces races
- // similar to tmpnam.
- int retries = 3;
- while (--retries) {
- std::string name = GetRandomFileName();
- if (!FileExists(name))
- return name;
- }
- std::cerr << "Failed to create unique temporary file name" << std::endl;
- std::abort();
-}
-
-std::string GetFileReporterOutput(int argc, char* argv[]) {
- std::vector<char*> new_argv(argv, argv + argc);
- assert(static_cast<decltype(new_argv)::size_type>(argc) == new_argv.size());
-
- std::string tmp_file_name = GetTempFileName();
- std::cout << "Will be using this as the tmp file: " << tmp_file_name << '\n';
-
- std::string tmp = "--benchmark_out=";
- tmp += tmp_file_name;
- new_argv.emplace_back(const_cast<char*>(tmp.c_str()));
-
- argc = int(new_argv.size());
-
- benchmark::Initialize(&argc, new_argv.data());
- benchmark::RunSpecifiedBenchmarks();
-
- // Read the output back from the file, and delete the file.
- std::ifstream tmp_stream(tmp_file_name);
- std::string output = std::string((std::istreambuf_iterator<char>(tmp_stream)),
- std::istreambuf_iterator<char>());
- std::remove(tmp_file_name.c_str());
-
- return output;
-}
+++ /dev/null
-
-#undef NDEBUG
-#include <cassert>
-#include <vector>
-
-#include "../src/check.h" // NOTE: check.h is for internal use only!
-#include "benchmark/benchmark.h"
-
-namespace {
-
-class TestReporter : public benchmark::ConsoleReporter {
- public:
- virtual void ReportRuns(const std::vector<Run>& report) {
- all_runs_.insert(all_runs_.end(), begin(report), end(report));
- ConsoleReporter::ReportRuns(report);
- }
-
- std::vector<Run> all_runs_;
-};
-
-struct TestCase {
- std::string name;
- const char* label;
- // Note: not explicit as we rely on it being converted through ADD_CASES.
- TestCase(const char* xname) : TestCase(xname, nullptr) {}
- TestCase(const char* xname, const char* xlabel)
- : name(xname), label(xlabel) {}
-
- typedef benchmark::BenchmarkReporter::Run Run;
-
- void CheckRun(Run const& run) const {
- // clang-format off
- CHECK(name == run.benchmark_name()) << "expected " << name << " got "
- << run.benchmark_name();
- if (label) {
- CHECK(run.report_label == label) << "expected " << label << " got "
- << run.report_label;
- } else {
- CHECK(run.report_label == "");
- }
- // clang-format on
- }
-};
-
-std::vector<TestCase> ExpectedResults;
-
-int AddCases(std::initializer_list<TestCase> const& v) {
- for (auto N : v) {
- ExpectedResults.push_back(N);
- }
- return 0;
-}
-
-#define CONCAT(x, y) CONCAT2(x, y)
-#define CONCAT2(x, y) x##y
-#define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases({__VA_ARGS__})
-
-} // end namespace
-
-typedef benchmark::internal::Benchmark* ReturnVal;
-
-//----------------------------------------------------------------------------//
-// Test RegisterBenchmark with no additional arguments
-//----------------------------------------------------------------------------//
-void BM_function(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_function);
-ReturnVal dummy = benchmark::RegisterBenchmark(
- "BM_function_manual_registration", BM_function);
-ADD_CASES({"BM_function"}, {"BM_function_manual_registration"});
-
-//----------------------------------------------------------------------------//
-// Test RegisterBenchmark with additional arguments
-// Note: GCC <= 4.8 do not support this form of RegisterBenchmark because they
-// reject the variadic pack expansion of lambda captures.
-//----------------------------------------------------------------------------//
-#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
-
-void BM_extra_args(benchmark::State& st, const char* label) {
- for (auto _ : st) {
- }
- st.SetLabel(label);
-}
-int RegisterFromFunction() {
- std::pair<const char*, const char*> cases[] = {
- {"test1", "One"}, {"test2", "Two"}, {"test3", "Three"}};
- for (auto const& c : cases)
- benchmark::RegisterBenchmark(c.first, &BM_extra_args, c.second);
- return 0;
-}
-int dummy2 = RegisterFromFunction();
-ADD_CASES({"test1", "One"}, {"test2", "Two"}, {"test3", "Three"});
-
-#endif // BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
-
-//----------------------------------------------------------------------------//
-// Test RegisterBenchmark with different callable types
-//----------------------------------------------------------------------------//
-
-struct CustomFixture {
- void operator()(benchmark::State& st) {
- for (auto _ : st) {
- }
- }
-};
-
-void TestRegistrationAtRuntime() {
-#ifdef BENCHMARK_HAS_CXX11
- {
- CustomFixture fx;
- benchmark::RegisterBenchmark("custom_fixture", fx);
- AddCases({"custom_fixture"});
- }
-#endif
-#ifndef BENCHMARK_HAS_NO_VARIADIC_REGISTER_BENCHMARK
- {
- const char* x = "42";
- auto capturing_lam = [=](benchmark::State& st) {
- for (auto _ : st) {
- }
- st.SetLabel(x);
- };
- benchmark::RegisterBenchmark("lambda_benchmark", capturing_lam);
- AddCases({{"lambda_benchmark", x}});
- }
-#endif
-}
-
-// Test that all benchmarks, registered at either during static init or runtime,
-// are run and the results are passed to the reported.
-void RunTestOne() {
- TestRegistrationAtRuntime();
-
- TestReporter test_reporter;
- benchmark::RunSpecifiedBenchmarks(&test_reporter);
-
- typedef benchmark::BenchmarkReporter::Run Run;
- auto EB = ExpectedResults.begin();
-
- for (Run const& run : test_reporter.all_runs_) {
- assert(EB != ExpectedResults.end());
- EB->CheckRun(run);
- ++EB;
- }
- assert(EB == ExpectedResults.end());
-}
-
-// Test that ClearRegisteredBenchmarks() clears all previously registered
-// benchmarks.
-// Also test that new benchmarks can be registered and ran afterwards.
-void RunTestTwo() {
- assert(ExpectedResults.size() != 0 &&
- "must have at least one registered benchmark");
- ExpectedResults.clear();
- benchmark::ClearRegisteredBenchmarks();
-
- TestReporter test_reporter;
- size_t num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter);
- assert(num_ran == 0);
- assert(test_reporter.all_runs_.begin() == test_reporter.all_runs_.end());
-
- TestRegistrationAtRuntime();
- num_ran = benchmark::RunSpecifiedBenchmarks(&test_reporter);
- assert(num_ran == ExpectedResults.size());
-
- typedef benchmark::BenchmarkReporter::Run Run;
- auto EB = ExpectedResults.begin();
-
- for (Run const& run : test_reporter.all_runs_) {
- assert(EB != ExpectedResults.end());
- EB->CheckRun(run);
- ++EB;
- }
- assert(EB == ExpectedResults.end());
-}
-
-int main(int argc, char* argv[]) {
- benchmark::Initialize(&argc, argv);
-
- RunTestOne();
- RunTestTwo();
-}
+++ /dev/null
-
-#undef NDEBUG
-#include <cstdio>
-#include <string>
-
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-// Ok this test is super ugly. We want to check what happens with the file
-// reporter in the presence of ReportAggregatesOnly().
-// We do not care about console output, the normal tests check that already.
-
-void BM_SummaryRepeat(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_SummaryRepeat)->Repetitions(3)->ReportAggregatesOnly();
-
-int main(int argc, char* argv[]) {
- const std::string output = GetFileReporterOutput(argc, argv);
-
- if (SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3") != 3 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_mean\"") != 1 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_median\"") !=
- 1 ||
- SubstrCnt(output, "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"") !=
- 1) {
- std::cout << "Precondition mismatch. Expected to only find three "
- "occurrences of \"BM_SummaryRepeat/repeats:3\" substring:\n"
- "\"name\": \"BM_SummaryRepeat/repeats:3_mean\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3_median\", "
- "\"name\": \"BM_SummaryRepeat/repeats:3_stddev\"\nThe entire "
- "output:\n";
- std::cout << output;
- return 1;
- }
-
- return 0;
-}
+++ /dev/null
-
-#undef NDEBUG
-#include <utility>
-
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-// ========================================================================= //
-// ---------------------- Testing Prologue Output -------------------------- //
-// ========================================================================= //
-
-ADD_CASES(TC_ConsoleOut, {{"^[-]+$", MR_Next},
- {"^Benchmark %s Time %s CPU %s Iterations$", MR_Next},
- {"^[-]+$", MR_Next}});
-static int AddContextCases() {
- AddCases(TC_ConsoleErr,
- {
- {"%int[-/]%int[-/]%int %int:%int:%int$", MR_Default},
- {"Running .*/reporter_output_test(\\.exe)?$", MR_Next},
- {"Run on \\(%int X %float MHz CPU s?\\)", MR_Next},
- });
- AddCases(TC_JSONOut,
- {{"^\\{", MR_Default},
- {"\"context\":", MR_Next},
- {"\"date\": \"", MR_Next},
- {"\"host_name\":", MR_Next},
- {"\"executable\": \".*(/|\\\\)reporter_output_test(\\.exe)?\",",
- MR_Next},
- {"\"num_cpus\": %int,$", MR_Next},
- {"\"mhz_per_cpu\": %float,$", MR_Next},
- {"\"cpu_scaling_enabled\": ", MR_Next},
- {"\"caches\": \\[$", MR_Next}});
- auto const& Info = benchmark::CPUInfo::Get();
- auto const& Caches = Info.caches;
- if (!Caches.empty()) {
- AddCases(TC_ConsoleErr, {{"CPU Caches:$", MR_Next}});
- }
- for (size_t I = 0; I < Caches.size(); ++I) {
- std::string num_caches_str =
- Caches[I].num_sharing != 0 ? " \\(x%int\\)$" : "$";
- AddCases(TC_ConsoleErr,
- {{"L%int (Data|Instruction|Unified) %int KiB" + num_caches_str,
- MR_Next}});
- AddCases(TC_JSONOut, {{"\\{$", MR_Next},
- {"\"type\": \"", MR_Next},
- {"\"level\": %int,$", MR_Next},
- {"\"size\": %int,$", MR_Next},
- {"\"num_sharing\": %int$", MR_Next},
- {"}[,]{0,1}$", MR_Next}});
- }
- AddCases(TC_JSONOut, {{"],$"}});
- auto const& LoadAvg = Info.load_avg;
- if (!LoadAvg.empty()) {
- AddCases(TC_ConsoleErr,
- {{"Load Average: (%float, ){0,2}%float$", MR_Next}});
- }
- AddCases(TC_JSONOut, {{"\"load_avg\": \\[(%float,?){0,3}],$", MR_Next}});
- return 0;
-}
-int dummy_register = AddContextCases();
-ADD_CASES(TC_CSVOut, {{"%csv_header"}});
-
-// ========================================================================= //
-// ------------------------ Testing Basic Output --------------------------- //
-// ========================================================================= //
-
-void BM_basic(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_basic);
-
-ADD_CASES(TC_ConsoleOut, {{"^BM_basic %console_report$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_basic\",$"},
- {"\"run_name\": \"BM_basic\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\"$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_basic\",%csv_report$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Bytes per Second Output ---------------- //
-// ========================================================================= //
-
-void BM_bytes_per_second(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- state.SetBytesProcessed(1);
-}
-BENCHMARK(BM_bytes_per_second);
-
-ADD_CASES(TC_ConsoleOut, {{"^BM_bytes_per_second %console_report "
- "bytes_per_second=%float[kM]{0,1}/s$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_bytes_per_second\",$"},
- {"\"run_name\": \"BM_bytes_per_second\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bytes_per_second\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_bytes_per_second\",%csv_bytes_report$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Items per Second Output ---------------- //
-// ========================================================================= //
-
-void BM_items_per_second(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- state.SetItemsProcessed(1);
-}
-BENCHMARK(BM_items_per_second);
-
-ADD_CASES(TC_ConsoleOut, {{"^BM_items_per_second %console_report "
- "items_per_second=%float[kM]{0,1}/s$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_items_per_second\",$"},
- {"\"run_name\": \"BM_items_per_second\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"items_per_second\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_items_per_second\",%csv_items_report$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Label Output --------------------------- //
-// ========================================================================= //
-
-void BM_label(benchmark::State& state) {
- for (auto _ : state) {
- }
- state.SetLabel("some label");
-}
-BENCHMARK(BM_label);
-
-ADD_CASES(TC_ConsoleOut, {{"^BM_label %console_report some label$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_label\",$"},
- {"\"run_name\": \"BM_label\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"label\": \"some label\"$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_label\",%csv_label_report_begin\"some "
- "label\"%csv_label_report_end$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Error Output --------------------------- //
-// ========================================================================= //
-
-void BM_error(benchmark::State& state) {
- state.SkipWithError("message");
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_error);
-ADD_CASES(TC_ConsoleOut, {{"^BM_error[ ]+ERROR OCCURRED: 'message'$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_error\",$"},
- {"\"run_name\": \"BM_error\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"error_occurred\": true,$", MR_Next},
- {"\"error_message\": \"message\",$", MR_Next}});
-
-ADD_CASES(TC_CSVOut, {{"^\"BM_error\",,,,,,,,true,\"message\"$"}});
-
-// ========================================================================= //
-// ------------------------ Testing No Arg Name Output -----------------------
-// //
-// ========================================================================= //
-
-void BM_no_arg_name(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_no_arg_name)->Arg(3);
-ADD_CASES(TC_ConsoleOut, {{"^BM_no_arg_name/3 %console_report$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_no_arg_name/3\",$"},
- {"\"run_name\": \"BM_no_arg_name/3\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_no_arg_name/3\",%csv_report$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Arg Name Output ----------------------- //
-// ========================================================================= //
-
-void BM_arg_name(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_arg_name)->ArgName("first")->Arg(3);
-ADD_CASES(TC_ConsoleOut, {{"^BM_arg_name/first:3 %console_report$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_arg_name/first:3\",$"},
- {"\"run_name\": \"BM_arg_name/first:3\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_arg_name/first:3\",%csv_report$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Arg Names Output ----------------------- //
-// ========================================================================= //
-
-void BM_arg_names(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_arg_names)->Args({2, 5, 4})->ArgNames({"first", "", "third"});
-ADD_CASES(TC_ConsoleOut,
- {{"^BM_arg_names/first:2/5/third:4 %console_report$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_arg_names/first:2/5/third:4\",$"},
- {"\"run_name\": \"BM_arg_names/first:2/5/third:4\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_arg_names/first:2/5/third:4\",%csv_report$"}});
-
-// ========================================================================= //
-// ------------------------ Testing Big Args Output ------------------------ //
-// ========================================================================= //
-
-void BM_BigArgs(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_BigArgs)->RangeMultiplier(2)->Range(1U << 30U, 1U << 31U);
-ADD_CASES(TC_ConsoleOut, {{"^BM_BigArgs/1073741824 %console_report$"},
- {"^BM_BigArgs/2147483648 %console_report$"}});
-
-// ========================================================================= //
-// ----------------------- Testing Complexity Output ----------------------- //
-// ========================================================================= //
-
-void BM_Complexity_O1(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- state.SetComplexityN(state.range(0));
-}
-BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(benchmark::o1);
-SET_SUBSTITUTIONS({{"%bigOStr", "[ ]* %float \\([0-9]+\\)"},
- {"%RMS", "[ ]*[0-9]+ %"}});
-ADD_CASES(TC_ConsoleOut, {{"^BM_Complexity_O1_BigO %bigOStr %bigOStr[ ]*$"},
- {"^BM_Complexity_O1_RMS %RMS %RMS[ ]*$"}});
-
-// ========================================================================= //
-// ----------------------- Testing Aggregate Output ------------------------ //
-// ========================================================================= //
-
-// Test that non-aggregate data is printed by default
-void BM_Repeat(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-// need two repetitions min to be able to output any aggregate output
-BENCHMARK(BM_Repeat)->Repetitions(2);
-ADD_CASES(TC_ConsoleOut,
- {{"^BM_Repeat/repeats:2 %console_report$"},
- {"^BM_Repeat/repeats:2 %console_report$"},
- {"^BM_Repeat/repeats:2_mean %console_time_only_report [ ]*2$"},
- {"^BM_Repeat/repeats:2_median %console_time_only_report [ ]*2$"},
- {"^BM_Repeat/repeats:2_stddev %console_time_only_report [ ]*2$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:2\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:2\"", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:2\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"repetition_index\": 1,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:2_mean\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:2_median\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:2_stddev\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:2\",%csv_report$"},
- {"^\"BM_Repeat/repeats:2\",%csv_report$"},
- {"^\"BM_Repeat/repeats:2_mean\",%csv_report$"},
- {"^\"BM_Repeat/repeats:2_median\",%csv_report$"},
- {"^\"BM_Repeat/repeats:2_stddev\",%csv_report$"}});
-// but for two repetitions, mean and median is the same, so let's repeat..
-BENCHMARK(BM_Repeat)->Repetitions(3);
-ADD_CASES(TC_ConsoleOut,
- {{"^BM_Repeat/repeats:3 %console_report$"},
- {"^BM_Repeat/repeats:3 %console_report$"},
- {"^BM_Repeat/repeats:3 %console_report$"},
- {"^BM_Repeat/repeats:3_mean %console_time_only_report [ ]*3$"},
- {"^BM_Repeat/repeats:3_median %console_time_only_report [ ]*3$"},
- {"^BM_Repeat/repeats:3_stddev %console_time_only_report [ ]*3$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:3\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:3\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"repetition_index\": 1,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:3\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"repetition_index\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:3_mean\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:3_median\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:3_stddev\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:3\",%csv_report$"},
- {"^\"BM_Repeat/repeats:3\",%csv_report$"},
- {"^\"BM_Repeat/repeats:3\",%csv_report$"},
- {"^\"BM_Repeat/repeats:3_mean\",%csv_report$"},
- {"^\"BM_Repeat/repeats:3_median\",%csv_report$"},
- {"^\"BM_Repeat/repeats:3_stddev\",%csv_report$"}});
-// median differs between even/odd number of repetitions, so just to be sure
-BENCHMARK(BM_Repeat)->Repetitions(4);
-ADD_CASES(TC_ConsoleOut,
- {{"^BM_Repeat/repeats:4 %console_report$"},
- {"^BM_Repeat/repeats:4 %console_report$"},
- {"^BM_Repeat/repeats:4 %console_report$"},
- {"^BM_Repeat/repeats:4 %console_report$"},
- {"^BM_Repeat/repeats:4_mean %console_time_only_report [ ]*4$"},
- {"^BM_Repeat/repeats:4_median %console_time_only_report [ ]*4$"},
- {"^BM_Repeat/repeats:4_stddev %console_time_only_report [ ]*4$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Repeat/repeats:4\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:4\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"repetition_index\": 1,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:4\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"repetition_index\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:4\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"repetition_index\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:4_mean\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 4,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:4_median\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 4,$", MR_Next},
- {"\"name\": \"BM_Repeat/repeats:4_stddev\",$"},
- {"\"run_name\": \"BM_Repeat/repeats:4\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 4,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 4,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Repeat/repeats:4\",%csv_report$"},
- {"^\"BM_Repeat/repeats:4\",%csv_report$"},
- {"^\"BM_Repeat/repeats:4\",%csv_report$"},
- {"^\"BM_Repeat/repeats:4\",%csv_report$"},
- {"^\"BM_Repeat/repeats:4_mean\",%csv_report$"},
- {"^\"BM_Repeat/repeats:4_median\",%csv_report$"},
- {"^\"BM_Repeat/repeats:4_stddev\",%csv_report$"}});
-
-// Test that a non-repeated test still prints non-aggregate results even when
-// only-aggregate reports have been requested
-void BM_RepeatOnce(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_RepeatOnce)->Repetitions(1)->ReportAggregatesOnly();
-ADD_CASES(TC_ConsoleOut, {{"^BM_RepeatOnce/repeats:1 %console_report$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_RepeatOnce/repeats:1\",$"},
- {"\"run_name\": \"BM_RepeatOnce/repeats:1\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 1,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_RepeatOnce/repeats:1\",%csv_report$"}});
-
-// Test that non-aggregate data is not reported
-void BM_SummaryRepeat(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_SummaryRepeat)->Repetitions(3)->ReportAggregatesOnly();
-ADD_CASES(
- TC_ConsoleOut,
- {{".*BM_SummaryRepeat/repeats:3 ", MR_Not},
- {"^BM_SummaryRepeat/repeats:3_mean %console_time_only_report [ ]*3$"},
- {"^BM_SummaryRepeat/repeats:3_median %console_time_only_report [ ]*3$"},
- {"^BM_SummaryRepeat/repeats:3_stddev %console_time_only_report [ ]*3$"}});
-ADD_CASES(TC_JSONOut,
- {{".*BM_SummaryRepeat/repeats:3 ", MR_Not},
- {"\"name\": \"BM_SummaryRepeat/repeats:3_mean\",$"},
- {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"name\": \"BM_SummaryRepeat/repeats:3_median\",$"},
- {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"name\": \"BM_SummaryRepeat/repeats:3_stddev\",$"},
- {"\"run_name\": \"BM_SummaryRepeat/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{".*BM_SummaryRepeat/repeats:3 ", MR_Not},
- {"^\"BM_SummaryRepeat/repeats:3_mean\",%csv_report$"},
- {"^\"BM_SummaryRepeat/repeats:3_median\",%csv_report$"},
- {"^\"BM_SummaryRepeat/repeats:3_stddev\",%csv_report$"}});
-
-// Test that non-aggregate data is not displayed.
-// NOTE: this test is kinda bad. we are only testing the display output.
-// But we don't check that the file output still contains everything...
-void BM_SummaryDisplay(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_SummaryDisplay)->Repetitions(2)->DisplayAggregatesOnly();
-ADD_CASES(
- TC_ConsoleOut,
- {{".*BM_SummaryDisplay/repeats:2 ", MR_Not},
- {"^BM_SummaryDisplay/repeats:2_mean %console_time_only_report [ ]*2$"},
- {"^BM_SummaryDisplay/repeats:2_median %console_time_only_report [ ]*2$"},
- {"^BM_SummaryDisplay/repeats:2_stddev %console_time_only_report [ ]*2$"}});
-ADD_CASES(TC_JSONOut,
- {{".*BM_SummaryDisplay/repeats:2 ", MR_Not},
- {"\"name\": \"BM_SummaryDisplay/repeats:2_mean\",$"},
- {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"name\": \"BM_SummaryDisplay/repeats:2_median\",$"},
- {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"name\": \"BM_SummaryDisplay/repeats:2_stddev\",$"},
- {"\"run_name\": \"BM_SummaryDisplay/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next}});
-ADD_CASES(TC_CSVOut,
- {{".*BM_SummaryDisplay/repeats:2 ", MR_Not},
- {"^\"BM_SummaryDisplay/repeats:2_mean\",%csv_report$"},
- {"^\"BM_SummaryDisplay/repeats:2_median\",%csv_report$"},
- {"^\"BM_SummaryDisplay/repeats:2_stddev\",%csv_report$"}});
-
-// Test repeats with custom time unit.
-void BM_RepeatTimeUnit(benchmark::State& state) {
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_RepeatTimeUnit)
- ->Repetitions(3)
- ->ReportAggregatesOnly()
- ->Unit(benchmark::kMicrosecond);
-ADD_CASES(
- TC_ConsoleOut,
- {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not},
- {"^BM_RepeatTimeUnit/repeats:3_mean %console_us_time_only_report [ ]*3$"},
- {"^BM_RepeatTimeUnit/repeats:3_median %console_us_time_only_report [ "
- "]*3$"},
- {"^BM_RepeatTimeUnit/repeats:3_stddev %console_us_time_only_report [ "
- "]*3$"}});
-ADD_CASES(TC_JSONOut,
- {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not},
- {"\"name\": \"BM_RepeatTimeUnit/repeats:3_mean\",$"},
- {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"time_unit\": \"us\",?$"},
- {"\"name\": \"BM_RepeatTimeUnit/repeats:3_median\",$"},
- {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"time_unit\": \"us\",?$"},
- {"\"name\": \"BM_RepeatTimeUnit/repeats:3_stddev\",$"},
- {"\"run_name\": \"BM_RepeatTimeUnit/repeats:3\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"time_unit\": \"us\",?$"}});
-ADD_CASES(TC_CSVOut,
- {{".*BM_RepeatTimeUnit/repeats:3 ", MR_Not},
- {"^\"BM_RepeatTimeUnit/repeats:3_mean\",%csv_us_report$"},
- {"^\"BM_RepeatTimeUnit/repeats:3_median\",%csv_us_report$"},
- {"^\"BM_RepeatTimeUnit/repeats:3_stddev\",%csv_us_report$"}});
-
-// ========================================================================= //
-// -------------------- Testing user-provided statistics ------------------- //
-// ========================================================================= //
-
-const auto UserStatistics = [](const std::vector<double>& v) {
- return v.back();
-};
-void BM_UserStats(benchmark::State& state) {
- for (auto _ : state) {
- state.SetIterationTime(150 / 10e8);
- }
-}
-// clang-format off
-BENCHMARK(BM_UserStats)
- ->Repetitions(3)
- ->Iterations(5)
- ->UseManualTime()
- ->ComputeStatistics("", UserStatistics);
-// clang-format on
-
-// check that user-provided stats is calculated, and is after the default-ones
-// empty string as name is intentional, it would sort before anything else
-ADD_CASES(TC_ConsoleOut, {{"^BM_UserStats/iterations:5/repeats:3/manual_time [ "
- "]* 150 ns %time [ ]*5$"},
- {"^BM_UserStats/iterations:5/repeats:3/manual_time [ "
- "]* 150 ns %time [ ]*5$"},
- {"^BM_UserStats/iterations:5/repeats:3/manual_time [ "
- "]* 150 ns %time [ ]*5$"},
- {"^BM_UserStats/iterations:5/repeats:3/"
- "manual_time_mean [ ]* 150 ns %time [ ]*3$"},
- {"^BM_UserStats/iterations:5/repeats:3/"
- "manual_time_median [ ]* 150 ns %time [ ]*3$"},
- {"^BM_UserStats/iterations:5/repeats:3/"
- "manual_time_stddev [ ]* 0.000 ns %time [ ]*3$"},
- {"^BM_UserStats/iterations:5/repeats:3/manual_time_ "
- "[ ]* 150 ns %time [ ]*3$"}});
-ADD_CASES(
- TC_JSONOut,
- {{"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": 5,$", MR_Next},
- {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next},
- {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"repetition_index\": 1,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": 5,$", MR_Next},
- {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next},
- {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"repetition_index\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": 5,$", MR_Next},
- {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next},
- {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_mean\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next},
- {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_median\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next},
- {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_stddev\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"name\": \"BM_UserStats/iterations:5/repeats:3/manual_time_\",$"},
- {"\"run_name\": \"BM_UserStats/iterations:5/repeats:3/manual_time\",$",
- MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 3,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"\",$", MR_Next},
- {"\"iterations\": 3,$", MR_Next},
- {"\"real_time\": 1\\.5(0)*e\\+(0)*2,$", MR_Next}});
-ADD_CASES(
- TC_CSVOut,
- {{"^\"BM_UserStats/iterations:5/repeats:3/manual_time\",%csv_report$"},
- {"^\"BM_UserStats/iterations:5/repeats:3/manual_time\",%csv_report$"},
- {"^\"BM_UserStats/iterations:5/repeats:3/manual_time\",%csv_report$"},
- {"^\"BM_UserStats/iterations:5/repeats:3/manual_time_mean\",%csv_report$"},
- {"^\"BM_UserStats/iterations:5/repeats:3/"
- "manual_time_median\",%csv_report$"},
- {"^\"BM_UserStats/iterations:5/repeats:3/"
- "manual_time_stddev\",%csv_report$"},
- {"^\"BM_UserStats/iterations:5/repeats:3/manual_time_\",%csv_report$"}});
-
-// ========================================================================= //
-// ------------------------- Testing StrEscape JSON ------------------------ //
-// ========================================================================= //
-#if 0 // enable when csv testing code correctly handles multi-line fields
-void BM_JSON_Format(benchmark::State& state) {
- state.SkipWithError("val\b\f\n\r\t\\\"with\"es,capes");
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_JSON_Format);
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_JSON_Format\",$"},
- {"\"run_name\": \"BM_JSON_Format\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"error_occurred\": true,$", MR_Next},
- {R"("error_message": "val\\b\\f\\n\\r\\t\\\\\\"with\\"es,capes",$)", MR_Next}});
-#endif
-// ========================================================================= //
-// -------------------------- Testing CsvEscape ---------------------------- //
-// ========================================================================= //
-
-void BM_CSV_Format(benchmark::State& state) {
- state.SkipWithError("\"freedom\"");
- for (auto _ : state) {
- }
-}
-BENCHMARK(BM_CSV_Format);
-ADD_CASES(TC_CSVOut, {{"^\"BM_CSV_Format\",,,,,,,,true,\"\"\"freedom\"\"\"$"}});
-
-// ========================================================================= //
-// --------------------------- TEST CASES END ------------------------------ //
-// ========================================================================= //
-
-int main(int argc, char* argv[]) { RunOutputTests(argc, argv); }
+++ /dev/null
-
-#undef NDEBUG
-#include <cassert>
-#include <vector>
-
-#include "../src/check.h" // NOTE: check.h is for internal use only!
-#include "benchmark/benchmark.h"
-
-namespace {
-
-class TestReporter : public benchmark::ConsoleReporter {
- public:
- virtual bool ReportContext(const Context& context) {
- return ConsoleReporter::ReportContext(context);
- };
-
- virtual void ReportRuns(const std::vector<Run>& report) {
- all_runs_.insert(all_runs_.end(), begin(report), end(report));
- ConsoleReporter::ReportRuns(report);
- }
-
- TestReporter() {}
- virtual ~TestReporter() {}
-
- mutable std::vector<Run> all_runs_;
-};
-
-struct TestCase {
- std::string name;
- bool error_occurred;
- std::string error_message;
-
- typedef benchmark::BenchmarkReporter::Run Run;
-
- void CheckRun(Run const& run) const {
- CHECK(name == run.benchmark_name())
- << "expected " << name << " got " << run.benchmark_name();
- CHECK(error_occurred == run.error_occurred);
- CHECK(error_message == run.error_message);
- if (error_occurred) {
- // CHECK(run.iterations == 0);
- } else {
- CHECK(run.iterations != 0);
- }
- }
-};
-
-std::vector<TestCase> ExpectedResults;
-
-int AddCases(const char* base_name, std::initializer_list<TestCase> const& v) {
- for (auto TC : v) {
- TC.name = base_name + TC.name;
- ExpectedResults.push_back(std::move(TC));
- }
- return 0;
-}
-
-#define CONCAT(x, y) CONCAT2(x, y)
-#define CONCAT2(x, y) x##y
-#define ADD_CASES(...) int CONCAT(dummy, __LINE__) = AddCases(__VA_ARGS__)
-
-} // end namespace
-
-void BM_error_no_running(benchmark::State& state) {
- state.SkipWithError("error message");
-}
-BENCHMARK(BM_error_no_running);
-ADD_CASES("BM_error_no_running", {{"", true, "error message"}});
-
-void BM_error_before_running(benchmark::State& state) {
- state.SkipWithError("error message");
- while (state.KeepRunning()) {
- assert(false);
- }
-}
-BENCHMARK(BM_error_before_running);
-ADD_CASES("BM_error_before_running", {{"", true, "error message"}});
-
-void BM_error_before_running_batch(benchmark::State& state) {
- state.SkipWithError("error message");
- while (state.KeepRunningBatch(17)) {
- assert(false);
- }
-}
-BENCHMARK(BM_error_before_running_batch);
-ADD_CASES("BM_error_before_running_batch", {{"", true, "error message"}});
-
-void BM_error_before_running_range_for(benchmark::State& state) {
- state.SkipWithError("error message");
- for (auto _ : state) {
- assert(false);
- }
-}
-BENCHMARK(BM_error_before_running_range_for);
-ADD_CASES("BM_error_before_running_range_for", {{"", true, "error message"}});
-
-void BM_error_during_running(benchmark::State& state) {
- int first_iter = true;
- while (state.KeepRunning()) {
- if (state.range(0) == 1 && state.thread_index <= (state.threads / 2)) {
- assert(first_iter);
- first_iter = false;
- state.SkipWithError("error message");
- } else {
- state.PauseTiming();
- state.ResumeTiming();
- }
- }
-}
-BENCHMARK(BM_error_during_running)->Arg(1)->Arg(2)->ThreadRange(1, 8);
-ADD_CASES("BM_error_during_running", {{"/1/threads:1", true, "error message"},
- {"/1/threads:2", true, "error message"},
- {"/1/threads:4", true, "error message"},
- {"/1/threads:8", true, "error message"},
- {"/2/threads:1", false, ""},
- {"/2/threads:2", false, ""},
- {"/2/threads:4", false, ""},
- {"/2/threads:8", false, ""}});
-
-void BM_error_during_running_ranged_for(benchmark::State& state) {
- assert(state.max_iterations > 3 && "test requires at least a few iterations");
- int first_iter = true;
- // NOTE: Users should not write the for loop explicitly.
- for (auto It = state.begin(), End = state.end(); It != End; ++It) {
- if (state.range(0) == 1) {
- assert(first_iter);
- first_iter = false;
- state.SkipWithError("error message");
- // Test the unfortunate but documented behavior that the ranged-for loop
- // doesn't automatically terminate when SkipWithError is set.
- assert(++It != End);
- break; // Required behavior
- }
- }
-}
-BENCHMARK(BM_error_during_running_ranged_for)->Arg(1)->Arg(2)->Iterations(5);
-ADD_CASES("BM_error_during_running_ranged_for",
- {{"/1/iterations:5", true, "error message"},
- {"/2/iterations:5", false, ""}});
-
-void BM_error_after_running(benchmark::State& state) {
- for (auto _ : state) {
- benchmark::DoNotOptimize(state.iterations());
- }
- if (state.thread_index <= (state.threads / 2))
- state.SkipWithError("error message");
-}
-BENCHMARK(BM_error_after_running)->ThreadRange(1, 8);
-ADD_CASES("BM_error_after_running", {{"/threads:1", true, "error message"},
- {"/threads:2", true, "error message"},
- {"/threads:4", true, "error message"},
- {"/threads:8", true, "error message"}});
-
-void BM_error_while_paused(benchmark::State& state) {
- bool first_iter = true;
- while (state.KeepRunning()) {
- if (state.range(0) == 1 && state.thread_index <= (state.threads / 2)) {
- assert(first_iter);
- first_iter = false;
- state.PauseTiming();
- state.SkipWithError("error message");
- } else {
- state.PauseTiming();
- state.ResumeTiming();
- }
- }
-}
-BENCHMARK(BM_error_while_paused)->Arg(1)->Arg(2)->ThreadRange(1, 8);
-ADD_CASES("BM_error_while_paused", {{"/1/threads:1", true, "error message"},
- {"/1/threads:2", true, "error message"},
- {"/1/threads:4", true, "error message"},
- {"/1/threads:8", true, "error message"},
- {"/2/threads:1", false, ""},
- {"/2/threads:2", false, ""},
- {"/2/threads:4", false, ""},
- {"/2/threads:8", false, ""}});
-
-int main(int argc, char* argv[]) {
- benchmark::Initialize(&argc, argv);
-
- TestReporter test_reporter;
- benchmark::RunSpecifiedBenchmarks(&test_reporter);
-
- typedef benchmark::BenchmarkReporter::Run Run;
- auto EB = ExpectedResults.begin();
-
- for (Run const& run : test_reporter.all_runs_) {
- assert(EB != ExpectedResults.end());
- EB->CheckRun(run);
- ++EB;
- }
- assert(EB == ExpectedResults.end());
-
- return 0;
-}
+++ /dev/null
-#include <benchmark/benchmark.h>
-
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wreturn-type"
-#endif
-
-// clang-format off
-extern "C" {
- extern int ExternInt;
- benchmark::State& GetState();
- void Fn();
-}
-// clang-format on
-
-using benchmark::State;
-
-// CHECK-LABEL: test_for_auto_loop:
-extern "C" int test_for_auto_loop() {
- State& S = GetState();
- int x = 42;
- // CHECK: [[CALL:call(q)*]] _ZN9benchmark5State16StartKeepRunningEv
- // CHECK-NEXT: testq %rbx, %rbx
- // CHECK-NEXT: je [[LOOP_END:.*]]
-
- for (auto _ : S) {
- // CHECK: .L[[LOOP_HEAD:[a-zA-Z0-9_]+]]:
- // CHECK-GNU-NEXT: subq $1, %rbx
- // CHECK-CLANG-NEXT: {{(addq \$1, %rax|incq %rax|addq \$-1, %rbx)}}
- // CHECK-NEXT: jne .L[[LOOP_HEAD]]
- benchmark::DoNotOptimize(x);
- }
- // CHECK: [[LOOP_END]]:
- // CHECK: [[CALL]] _ZN9benchmark5State17FinishKeepRunningEv
-
- // CHECK: movl $101, %eax
- // CHECK: ret
- return 101;
-}
-
-// CHECK-LABEL: test_while_loop:
-extern "C" int test_while_loop() {
- State& S = GetState();
- int x = 42;
-
- // CHECK: j{{(e|mp)}} .L[[LOOP_HEADER:[a-zA-Z0-9_]+]]
- // CHECK-NEXT: .L[[LOOP_BODY:[a-zA-Z0-9_]+]]:
- while (S.KeepRunning()) {
- // CHECK-GNU-NEXT: subq $1, %[[IREG:[a-z]+]]
- // CHECK-CLANG-NEXT: {{(addq \$-1,|decq)}} %[[IREG:[a-z]+]]
- // CHECK: movq %[[IREG]], [[DEST:.*]]
- benchmark::DoNotOptimize(x);
- }
- // CHECK-DAG: movq [[DEST]], %[[IREG]]
- // CHECK-DAG: testq %[[IREG]], %[[IREG]]
- // CHECK-DAG: jne .L[[LOOP_BODY]]
- // CHECK-DAG: .L[[LOOP_HEADER]]:
-
- // CHECK: cmpb $0
- // CHECK-NEXT: jne .L[[LOOP_END:[a-zA-Z0-9_]+]]
- // CHECK: [[CALL:call(q)*]] _ZN9benchmark5State16StartKeepRunningEv
-
- // CHECK: .L[[LOOP_END]]:
- // CHECK: [[CALL]] _ZN9benchmark5State17FinishKeepRunningEv
-
- // CHECK: movl $101, %eax
- // CHECK: ret
- return 101;
-}
+++ /dev/null
-//===---------------------------------------------------------------------===//
-// statistics_test - Unit tests for src/statistics.cc
-//===---------------------------------------------------------------------===//
-
-#include "../src/statistics.h"
-#include "gtest/gtest.h"
-
-namespace {
-TEST(StatisticsTest, Mean) {
- EXPECT_DOUBLE_EQ(benchmark::StatisticsMean({42, 42, 42, 42}), 42.0);
- EXPECT_DOUBLE_EQ(benchmark::StatisticsMean({1, 2, 3, 4}), 2.5);
- EXPECT_DOUBLE_EQ(benchmark::StatisticsMean({1, 2, 5, 10, 10, 14}), 7.0);
-}
-
-TEST(StatisticsTest, Median) {
- EXPECT_DOUBLE_EQ(benchmark::StatisticsMedian({42, 42, 42, 42}), 42.0);
- EXPECT_DOUBLE_EQ(benchmark::StatisticsMedian({1, 2, 3, 4}), 2.5);
- EXPECT_DOUBLE_EQ(benchmark::StatisticsMedian({1, 2, 5, 10, 10}), 5.0);
-}
-
-TEST(StatisticsTest, StdDev) {
- EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({101, 101, 101, 101}), 0.0);
- EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({1, 2, 3}), 1.0);
- EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({2.5, 2.4, 3.3, 4.2, 5.1}),
- 1.151086443322134);
-}
-
-} // end namespace
+++ /dev/null
-//===---------------------------------------------------------------------===//
-// statistics_test - Unit tests for src/statistics.cc
-//===---------------------------------------------------------------------===//
-
-#include "../src/string_util.h"
-#include "../src/internal_macros.h"
-#include "gtest/gtest.h"
-
-namespace {
-TEST(StringUtilTest, stoul) {
- {
- size_t pos = 0;
- EXPECT_EQ(0ul, benchmark::stoul("0", &pos));
- EXPECT_EQ(1ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(7ul, benchmark::stoul("7", &pos));
- EXPECT_EQ(1ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(135ul, benchmark::stoul("135", &pos));
- EXPECT_EQ(3ul, pos);
- }
-#if ULONG_MAX == 0xFFFFFFFFul
- {
- size_t pos = 0;
- EXPECT_EQ(0xFFFFFFFFul, benchmark::stoul("4294967295", &pos));
- EXPECT_EQ(10ul, pos);
- }
-#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFul
- {
- size_t pos = 0;
- EXPECT_EQ(0xFFFFFFFFFFFFFFFFul, benchmark::stoul("18446744073709551615", &pos));
- EXPECT_EQ(20ul, pos);
- }
-#endif
- {
- size_t pos = 0;
- EXPECT_EQ(10ul, benchmark::stoul("1010", &pos, 2));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(520ul, benchmark::stoul("1010", &pos, 8));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(1010ul, benchmark::stoul("1010", &pos, 10));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(4112ul, benchmark::stoul("1010", &pos, 16));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(0xBEEFul, benchmark::stoul("BEEF", &pos, 16));
- EXPECT_EQ(4ul, pos);
- }
-#ifndef BENCHMARK_HAS_NO_EXCEPTIONS
- {
- ASSERT_THROW(benchmark::stoul("this is a test"), std::invalid_argument);
- }
-#endif
-}
-
-TEST(StringUtilTest, stoi) {
- {
- size_t pos = 0;
- EXPECT_EQ(0, benchmark::stoi("0", &pos));
- EXPECT_EQ(1ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(-17, benchmark::stoi("-17", &pos));
- EXPECT_EQ(3ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(1357, benchmark::stoi("1357", &pos));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(10, benchmark::stoi("1010", &pos, 2));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(520, benchmark::stoi("1010", &pos, 8));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(1010, benchmark::stoi("1010", &pos, 10));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(4112, benchmark::stoi("1010", &pos, 16));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(0xBEEF, benchmark::stoi("BEEF", &pos, 16));
- EXPECT_EQ(4ul, pos);
- }
-#ifndef BENCHMARK_HAS_NO_EXCEPTIONS
- {
- ASSERT_THROW(benchmark::stoi("this is a test"), std::invalid_argument);
- }
-#endif
-}
-
-TEST(StringUtilTest, stod) {
- {
- size_t pos = 0;
- EXPECT_EQ(0.0, benchmark::stod("0", &pos));
- EXPECT_EQ(1ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(-84.0, benchmark::stod("-84", &pos));
- EXPECT_EQ(3ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(1234.0, benchmark::stod("1234", &pos));
- EXPECT_EQ(4ul, pos);
- }
- {
- size_t pos = 0;
- EXPECT_EQ(1.5, benchmark::stod("1.5", &pos));
- EXPECT_EQ(3ul, pos);
- }
- {
- size_t pos = 0;
- /* Note: exactly representable as double */
- EXPECT_EQ(-1.25e+9, benchmark::stod("-1.25e+9", &pos));
- EXPECT_EQ(8ul, pos);
- }
-#ifndef BENCHMARK_HAS_NO_EXCEPTIONS
- {
- ASSERT_THROW(benchmark::stod("this is a test"), std::invalid_argument);
- }
-#endif
-}
-
-} // end namespace
+++ /dev/null
-
-#include "benchmark/benchmark.h"
-
-#include <cassert>
-#include <memory>
-
-template <typename T>
-class MyFixture : public ::benchmark::Fixture {
- public:
- MyFixture() : data(0) {}
-
- T data;
-};
-
-BENCHMARK_TEMPLATE_F(MyFixture, Foo, int)(benchmark::State& st) {
- for (auto _ : st) {
- data += 1;
- }
-}
-
-BENCHMARK_TEMPLATE_DEFINE_F(MyFixture, Bar, double)(benchmark::State& st) {
- for (auto _ : st) {
- data += 1.0;
- }
-}
-BENCHMARK_REGISTER_F(MyFixture, Bar);
-
-BENCHMARK_MAIN();
+++ /dev/null
-
-#undef NDEBUG
-
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-// @todo: <jpmag> this checks the full output at once; the rule for
-// CounterSet1 was failing because it was not matching "^[-]+$".
-// @todo: <jpmag> check that the counters are vertically aligned.
-ADD_CASES(
- TC_ConsoleOut,
- {
- // keeping these lines long improves readability, so:
- // clang-format off
- {"^[-]+$", MR_Next},
- {"^Benchmark %s Time %s CPU %s Iterations %s Bar %s Bat %s Baz %s Foo %s Frob %s Lob$", MR_Next},
- {"^[-]+$", MR_Next},
- {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_Counters_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next},
- {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next},
- {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next},
- {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next},
- {"^BM_CounterRates_Tabular/threads:%int %console_report [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s [ ]*%hrfloat/s$", MR_Next},
- {"^[-]+$", MR_Next},
- {"^Benchmark %s Time %s CPU %s Iterations %s Bar %s Baz %s Foo$", MR_Next},
- {"^[-]+$", MR_Next},
- {"^BM_CounterSet0_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet0_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet0_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet0_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet0_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet1_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet1_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet1_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet1_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet1_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^[-]+$", MR_Next},
- {"^Benchmark %s Time %s CPU %s Iterations %s Bat %s Baz %s Foo$", MR_Next},
- {"^[-]+$", MR_Next},
- {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next},
- {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$"},
- // clang-format on
- });
-ADD_CASES(TC_CSVOut, {{"%csv_header,"
- "\"Bar\",\"Bat\",\"Baz\",\"Foo\",\"Frob\",\"Lob\""}});
-
-// ========================================================================= //
-// ------------------------- Tabular Counters Output ----------------------- //
-// ========================================================================= //
-
-void BM_Counters_Tabular(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters.insert({
- {"Foo", {1, bm::Counter::kAvgThreads}},
- {"Bar", {2, bm::Counter::kAvgThreads}},
- {"Baz", {4, bm::Counter::kAvgThreads}},
- {"Bat", {8, bm::Counter::kAvgThreads}},
- {"Frob", {16, bm::Counter::kAvgThreads}},
- {"Lob", {32, bm::Counter::kAvgThreads}},
- });
-}
-BENCHMARK(BM_Counters_Tabular)->ThreadRange(1, 16);
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Tabular/threads:%int\",$"},
- {"\"run_name\": \"BM_Counters_Tabular/threads:%int\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"Bar\": %float,$", MR_Next},
- {"\"Bat\": %float,$", MR_Next},
- {"\"Baz\": %float,$", MR_Next},
- {"\"Foo\": %float,$", MR_Next},
- {"\"Frob\": %float,$", MR_Next},
- {"\"Lob\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Tabular/threads:%int\",%csv_report,"
- "%float,%float,%float,%float,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckTabular(Results const& e) {
- CHECK_COUNTER_VALUE(e, int, "Foo", EQ, 1);
- CHECK_COUNTER_VALUE(e, int, "Bar", EQ, 2);
- CHECK_COUNTER_VALUE(e, int, "Baz", EQ, 4);
- CHECK_COUNTER_VALUE(e, int, "Bat", EQ, 8);
- CHECK_COUNTER_VALUE(e, int, "Frob", EQ, 16);
- CHECK_COUNTER_VALUE(e, int, "Lob", EQ, 32);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_Tabular/threads:%int", &CheckTabular);
-
-// ========================================================================= //
-// -------------------- Tabular+Rate Counters Output ----------------------- //
-// ========================================================================= //
-
-void BM_CounterRates_Tabular(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters.insert({
- {"Foo", {1, bm::Counter::kAvgThreadsRate}},
- {"Bar", {2, bm::Counter::kAvgThreadsRate}},
- {"Baz", {4, bm::Counter::kAvgThreadsRate}},
- {"Bat", {8, bm::Counter::kAvgThreadsRate}},
- {"Frob", {16, bm::Counter::kAvgThreadsRate}},
- {"Lob", {32, bm::Counter::kAvgThreadsRate}},
- });
-}
-BENCHMARK(BM_CounterRates_Tabular)->ThreadRange(1, 16);
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_CounterRates_Tabular/threads:%int\",$"},
- {"\"run_name\": \"BM_CounterRates_Tabular/threads:%int\",$",
- MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"Bar\": %float,$", MR_Next},
- {"\"Bat\": %float,$", MR_Next},
- {"\"Baz\": %float,$", MR_Next},
- {"\"Foo\": %float,$", MR_Next},
- {"\"Frob\": %float,$", MR_Next},
- {"\"Lob\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_CounterRates_Tabular/threads:%int\",%csv_report,"
- "%float,%float,%float,%float,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckTabularRate(Results const& e) {
- double t = e.DurationCPUTime();
- CHECK_FLOAT_COUNTER_VALUE(e, "Foo", EQ, 1. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "Bar", EQ, 2. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "Baz", EQ, 4. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "Bat", EQ, 8. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "Frob", EQ, 16. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "Lob", EQ, 32. / t, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_CounterRates_Tabular/threads:%int",
- &CheckTabularRate);
-
-// ========================================================================= //
-// ------------------------- Tabular Counters Output ----------------------- //
-// ========================================================================= //
-
-// set only some of the counters
-void BM_CounterSet0_Tabular(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters.insert({
- {"Foo", {10, bm::Counter::kAvgThreads}},
- {"Bar", {20, bm::Counter::kAvgThreads}},
- {"Baz", {40, bm::Counter::kAvgThreads}},
- });
-}
-BENCHMARK(BM_CounterSet0_Tabular)->ThreadRange(1, 16);
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_CounterSet0_Tabular/threads:%int\",$"},
- {"\"run_name\": \"BM_CounterSet0_Tabular/threads:%int\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"Bar\": %float,$", MR_Next},
- {"\"Baz\": %float,$", MR_Next},
- {"\"Foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_CounterSet0_Tabular/threads:%int\",%csv_report,"
- "%float,,%float,%float,,"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckSet0(Results const& e) {
- CHECK_COUNTER_VALUE(e, int, "Foo", EQ, 10);
- CHECK_COUNTER_VALUE(e, int, "Bar", EQ, 20);
- CHECK_COUNTER_VALUE(e, int, "Baz", EQ, 40);
-}
-CHECK_BENCHMARK_RESULTS("BM_CounterSet0_Tabular", &CheckSet0);
-
-// again.
-void BM_CounterSet1_Tabular(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters.insert({
- {"Foo", {15, bm::Counter::kAvgThreads}},
- {"Bar", {25, bm::Counter::kAvgThreads}},
- {"Baz", {45, bm::Counter::kAvgThreads}},
- });
-}
-BENCHMARK(BM_CounterSet1_Tabular)->ThreadRange(1, 16);
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_CounterSet1_Tabular/threads:%int\",$"},
- {"\"run_name\": \"BM_CounterSet1_Tabular/threads:%int\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"Bar\": %float,$", MR_Next},
- {"\"Baz\": %float,$", MR_Next},
- {"\"Foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_CounterSet1_Tabular/threads:%int\",%csv_report,"
- "%float,,%float,%float,,"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckSet1(Results const& e) {
- CHECK_COUNTER_VALUE(e, int, "Foo", EQ, 15);
- CHECK_COUNTER_VALUE(e, int, "Bar", EQ, 25);
- CHECK_COUNTER_VALUE(e, int, "Baz", EQ, 45);
-}
-CHECK_BENCHMARK_RESULTS("BM_CounterSet1_Tabular/threads:%int", &CheckSet1);
-
-// ========================================================================= //
-// ------------------------- Tabular Counters Output ----------------------- //
-// ========================================================================= //
-
-// set only some of the counters, different set now.
-void BM_CounterSet2_Tabular(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters.insert({
- {"Foo", {10, bm::Counter::kAvgThreads}},
- {"Bat", {30, bm::Counter::kAvgThreads}},
- {"Baz", {40, bm::Counter::kAvgThreads}},
- });
-}
-BENCHMARK(BM_CounterSet2_Tabular)->ThreadRange(1, 16);
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_CounterSet2_Tabular/threads:%int\",$"},
- {"\"run_name\": \"BM_CounterSet2_Tabular/threads:%int\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"Bat\": %float,$", MR_Next},
- {"\"Baz\": %float,$", MR_Next},
- {"\"Foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_CounterSet2_Tabular/threads:%int\",%csv_report,"
- ",%float,%float,%float,,"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckSet2(Results const& e) {
- CHECK_COUNTER_VALUE(e, int, "Foo", EQ, 10);
- CHECK_COUNTER_VALUE(e, int, "Bat", EQ, 30);
- CHECK_COUNTER_VALUE(e, int, "Baz", EQ, 40);
-}
-CHECK_BENCHMARK_RESULTS("BM_CounterSet2_Tabular", &CheckSet2);
-
-// ========================================================================= //
-// --------------------------- TEST CASES END ------------------------------ //
-// ========================================================================= //
-
-int main(int argc, char* argv[]) { RunOutputTests(argc, argv); }
+++ /dev/null
-
-#undef NDEBUG
-
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-// ========================================================================= //
-// ---------------------- Testing Prologue Output -------------------------- //
-// ========================================================================= //
-
-// clang-format off
-
-ADD_CASES(TC_ConsoleOut,
- {{"^[-]+$", MR_Next},
- {"^Benchmark %s Time %s CPU %s Iterations UserCounters...$", MR_Next},
- {"^[-]+$", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"%csv_header,\"bar\",\"foo\""}});
-
-// clang-format on
-
-// ========================================================================= //
-// ------------------------- Simple Counters Output ------------------------ //
-// ========================================================================= //
-
-void BM_Counters_Simple(benchmark::State& state) {
- for (auto _ : state) {
- }
- state.counters["foo"] = 1;
- state.counters["bar"] = 2 * (double)state.iterations();
-}
-BENCHMARK(BM_Counters_Simple);
-ADD_CASES(TC_ConsoleOut,
- {{"^BM_Counters_Simple %console_report bar=%hrfloat foo=%hrfloat$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Simple\",$"},
- {"\"run_name\": \"BM_Counters_Simple\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Simple\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckSimple(Results const& e) {
- double its = e.NumIterations();
- CHECK_COUNTER_VALUE(e, int, "foo", EQ, 1);
- // check that the value of bar is within 0.1% of the expected value
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. * its, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_Simple", &CheckSimple);
-
-// ========================================================================= //
-// --------------------- Counters+Items+Bytes/s Output --------------------- //
-// ========================================================================= //
-
-namespace {
-int num_calls1 = 0;
-}
-void BM_Counters_WithBytesAndItemsPSec(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- state.counters["foo"] = 1;
- state.counters["bar"] = ++num_calls1;
- state.SetBytesProcessed(364);
- state.SetItemsProcessed(150);
-}
-BENCHMARK(BM_Counters_WithBytesAndItemsPSec);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_WithBytesAndItemsPSec %console_report "
- "bar=%hrfloat bytes_per_second=%hrfloat/s "
- "foo=%hrfloat items_per_second=%hrfloat/s$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_WithBytesAndItemsPSec\",$"},
- {"\"run_name\": \"BM_Counters_WithBytesAndItemsPSec\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"bytes_per_second\": %float,$", MR_Next},
- {"\"foo\": %float,$", MR_Next},
- {"\"items_per_second\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_WithBytesAndItemsPSec\","
- "%csv_bytes_items_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckBytesAndItemsPSec(Results const& e) {
- double t = e.DurationCPUTime(); // this (and not real time) is the time used
- CHECK_COUNTER_VALUE(e, int, "foo", EQ, 1);
- CHECK_COUNTER_VALUE(e, int, "bar", EQ, num_calls1);
- // check that the values are within 0.1% of the expected values
- CHECK_FLOAT_RESULT_VALUE(e, "bytes_per_second", EQ, 364. / t, 0.001);
- CHECK_FLOAT_RESULT_VALUE(e, "items_per_second", EQ, 150. / t, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_WithBytesAndItemsPSec",
- &CheckBytesAndItemsPSec);
-
-// ========================================================================= //
-// ------------------------- Rate Counters Output -------------------------- //
-// ========================================================================= //
-
-void BM_Counters_Rate(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{1, bm::Counter::kIsRate};
- state.counters["bar"] = bm::Counter{2, bm::Counter::kIsRate};
-}
-BENCHMARK(BM_Counters_Rate);
-ADD_CASES(
- TC_ConsoleOut,
- {{"^BM_Counters_Rate %console_report bar=%hrfloat/s foo=%hrfloat/s$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Rate\",$"},
- {"\"run_name\": \"BM_Counters_Rate\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Rate\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckRate(Results const& e) {
- double t = e.DurationCPUTime(); // this (and not real time) is the time used
- // check that the values are within 0.1% of the expected values
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / t, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_Rate", &CheckRate);
-
-// ========================================================================= //
-// ----------------------- Inverted Counters Output ------------------------ //
-// ========================================================================= //
-
-void BM_Invert(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{0.0001, bm::Counter::kInvert};
- state.counters["bar"] = bm::Counter{10000, bm::Counter::kInvert};
-}
-BENCHMARK(BM_Invert);
-ADD_CASES(TC_ConsoleOut,
- {{"^BM_Invert %console_report bar=%hrfloatu foo=%hrfloatk$"}});
-ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Invert\",$"},
- {"\"run_name\": \"BM_Invert\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Invert\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckInvert(Results const& e) {
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 10000, 0.0001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 0.0001, 0.0001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Invert", &CheckInvert);
-
-// ========================================================================= //
-// ------------------------- InvertedRate Counters Output
-// -------------------------- //
-// ========================================================================= //
-
-void BM_Counters_InvertedRate(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters["foo"] =
- bm::Counter{1, bm::Counter::kIsRate | bm::Counter::kInvert};
- state.counters["bar"] =
- bm::Counter{8192, bm::Counter::kIsRate | bm::Counter::kInvert};
-}
-BENCHMARK(BM_Counters_InvertedRate);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_InvertedRate %console_report "
- "bar=%hrfloats foo=%hrfloats$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_InvertedRate\",$"},
- {"\"run_name\": \"BM_Counters_InvertedRate\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut,
- {{"^\"BM_Counters_InvertedRate\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckInvertedRate(Results const& e) {
- double t = e.DurationCPUTime(); // this (and not real time) is the time used
- // check that the values are within 0.1% of the expected values
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, t / 8192.0, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_InvertedRate", &CheckInvertedRate);
-
-// ========================================================================= //
-// ------------------------- Thread Counters Output ------------------------ //
-// ========================================================================= //
-
-void BM_Counters_Threads(benchmark::State& state) {
- for (auto _ : state) {
- }
- state.counters["foo"] = 1;
- state.counters["bar"] = 2;
-}
-BENCHMARK(BM_Counters_Threads)->ThreadRange(1, 8);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Threads/threads:%int %console_report "
- "bar=%hrfloat foo=%hrfloat$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Threads/threads:%int\",$"},
- {"\"run_name\": \"BM_Counters_Threads/threads:%int\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(
- TC_CSVOut,
- {{"^\"BM_Counters_Threads/threads:%int\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckThreads(Results const& e) {
- CHECK_COUNTER_VALUE(e, int, "foo", EQ, e.NumThreads());
- CHECK_COUNTER_VALUE(e, int, "bar", EQ, 2 * e.NumThreads());
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_Threads/threads:%int", &CheckThreads);
-
-// ========================================================================= //
-// ---------------------- ThreadAvg Counters Output ------------------------ //
-// ========================================================================= //
-
-void BM_Counters_AvgThreads(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgThreads};
- state.counters["bar"] = bm::Counter{2, bm::Counter::kAvgThreads};
-}
-BENCHMARK(BM_Counters_AvgThreads)->ThreadRange(1, 8);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgThreads/threads:%int "
- "%console_report bar=%hrfloat foo=%hrfloat$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_AvgThreads/threads:%int\",$"},
- {"\"run_name\": \"BM_Counters_AvgThreads/threads:%int\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(
- TC_CSVOut,
- {{"^\"BM_Counters_AvgThreads/threads:%int\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckAvgThreads(Results const& e) {
- CHECK_COUNTER_VALUE(e, int, "foo", EQ, 1);
- CHECK_COUNTER_VALUE(e, int, "bar", EQ, 2);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreads/threads:%int",
- &CheckAvgThreads);
-
-// ========================================================================= //
-// ---------------------- ThreadAvg Counters Output ------------------------ //
-// ========================================================================= //
-
-void BM_Counters_AvgThreadsRate(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgThreadsRate};
- state.counters["bar"] = bm::Counter{2, bm::Counter::kAvgThreadsRate};
-}
-BENCHMARK(BM_Counters_AvgThreadsRate)->ThreadRange(1, 8);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgThreadsRate/threads:%int "
- "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$"},
- {"\"run_name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$",
- MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_AvgThreadsRate/"
- "threads:%int\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckAvgThreadsRate(Results const& e) {
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / e.DurationCPUTime(), 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / e.DurationCPUTime(), 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreadsRate/threads:%int",
- &CheckAvgThreadsRate);
-
-// ========================================================================= //
-// ------------------- IterationInvariant Counters Output ------------------ //
-// ========================================================================= //
-
-void BM_Counters_IterationInvariant(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{1, bm::Counter::kIsIterationInvariant};
- state.counters["bar"] = bm::Counter{2, bm::Counter::kIsIterationInvariant};
-}
-BENCHMARK(BM_Counters_IterationInvariant);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_IterationInvariant %console_report "
- "bar=%hrfloat foo=%hrfloat$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_IterationInvariant\",$"},
- {"\"run_name\": \"BM_Counters_IterationInvariant\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut,
- {{"^\"BM_Counters_IterationInvariant\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckIterationInvariant(Results const& e) {
- double its = e.NumIterations();
- // check that the values are within 0.1% of the expected value
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, its, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. * its, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_IterationInvariant",
- &CheckIterationInvariant);
-
-// ========================================================================= //
-// ----------------- IterationInvariantRate Counters Output ---------------- //
-// ========================================================================= //
-
-void BM_Counters_kIsIterationInvariantRate(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters["foo"] =
- bm::Counter{1, bm::Counter::kIsIterationInvariantRate};
- state.counters["bar"] =
- bm::Counter{2, bm::Counter::kIsRate | bm::Counter::kIsIterationInvariant};
-}
-BENCHMARK(BM_Counters_kIsIterationInvariantRate);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kIsIterationInvariantRate "
- "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_kIsIterationInvariantRate\",$"},
- {"\"run_name\": \"BM_Counters_kIsIterationInvariantRate\",$",
- MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_kIsIterationInvariantRate\",%csv_report,"
- "%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckIsIterationInvariantRate(Results const& e) {
- double its = e.NumIterations();
- double t = e.DurationCPUTime(); // this (and not real time) is the time used
- // check that the values are within 0.1% of the expected values
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, its * 1. / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, its * 2. / t, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_kIsIterationInvariantRate",
- &CheckIsIterationInvariantRate);
-
-// ========================================================================= //
-// ------------------- AvgIterations Counters Output ------------------ //
-// ========================================================================= //
-
-void BM_Counters_AvgIterations(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgIterations};
- state.counters["bar"] = bm::Counter{2, bm::Counter::kAvgIterations};
-}
-BENCHMARK(BM_Counters_AvgIterations);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_AvgIterations %console_report "
- "bar=%hrfloat foo=%hrfloat$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_AvgIterations\",$"},
- {"\"run_name\": \"BM_Counters_AvgIterations\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut,
- {{"^\"BM_Counters_AvgIterations\",%csv_report,%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckAvgIterations(Results const& e) {
- double its = e.NumIterations();
- // check that the values are within 0.1% of the expected value
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / its, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / its, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_AvgIterations", &CheckAvgIterations);
-
-// ========================================================================= //
-// ----------------- AvgIterationsRate Counters Output ---------------- //
-// ========================================================================= //
-
-void BM_Counters_kAvgIterationsRate(benchmark::State& state) {
- for (auto _ : state) {
- // This test requires a non-zero CPU time to avoid divide-by-zero
- benchmark::DoNotOptimize(state.iterations());
- }
- namespace bm = benchmark;
- state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgIterationsRate};
- state.counters["bar"] =
- bm::Counter{2, bm::Counter::kIsRate | bm::Counter::kAvgIterations};
-}
-BENCHMARK(BM_Counters_kAvgIterationsRate);
-ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kAvgIterationsRate "
- "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_kAvgIterationsRate\",$"},
- {"\"run_name\": \"BM_Counters_kAvgIterationsRate\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 0,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"bar\": %float,$", MR_Next},
- {"\"foo\": %float$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_kAvgIterationsRate\",%csv_report,"
- "%float,%float$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckAvgIterationsRate(Results const& e) {
- double its = e.NumIterations();
- double t = e.DurationCPUTime(); // this (and not real time) is the time used
- // check that the values are within 0.1% of the expected values
- CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / its / t, 0.001);
- CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / its / t, 0.001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_kAvgIterationsRate",
- &CheckAvgIterationsRate);
-
-// ========================================================================= //
-// --------------------------- TEST CASES END ------------------------------ //
-// ========================================================================= //
-
-int main(int argc, char* argv[]) { RunOutputTests(argc, argv); }
+++ /dev/null
-
-#undef NDEBUG
-
-#include "benchmark/benchmark.h"
-#include "output_test.h"
-
-// ========================================================================= //
-// ------------------------ Thousands Customisation ------------------------ //
-// ========================================================================= //
-
-void BM_Counters_Thousands(benchmark::State& state) {
- for (auto _ : state) {
- }
- namespace bm = benchmark;
- state.counters.insert({
- {"t0_1000000DefaultBase",
- bm::Counter(1000 * 1000, bm::Counter::kDefaults)},
- {"t1_1000000Base1000", bm::Counter(1000 * 1000, bm::Counter::kDefaults,
- benchmark::Counter::OneK::kIs1000)},
- {"t2_1000000Base1024", bm::Counter(1000 * 1000, bm::Counter::kDefaults,
- benchmark::Counter::OneK::kIs1024)},
- {"t3_1048576Base1000", bm::Counter(1024 * 1024, bm::Counter::kDefaults,
- benchmark::Counter::OneK::kIs1000)},
- {"t4_1048576Base1024", bm::Counter(1024 * 1024, bm::Counter::kDefaults,
- benchmark::Counter::OneK::kIs1024)},
- });
-}
-BENCHMARK(BM_Counters_Thousands)->Repetitions(2);
-ADD_CASES(
- TC_ConsoleOut,
- {
- {"^BM_Counters_Thousands/repeats:2 %console_report "
- "t0_1000000DefaultBase=1000k "
- "t1_1000000Base1000=1000k t2_1000000Base1024=976.56[23]k "
- "t3_1048576Base1000=1048.58k t4_1048576Base1024=1024k$"},
- {"^BM_Counters_Thousands/repeats:2 %console_report "
- "t0_1000000DefaultBase=1000k "
- "t1_1000000Base1000=1000k t2_1000000Base1024=976.56[23]k "
- "t3_1048576Base1000=1048.58k t4_1048576Base1024=1024k$"},
- {"^BM_Counters_Thousands/repeats:2_mean %console_report "
- "t0_1000000DefaultBase=1000k t1_1000000Base1000=1000k "
- "t2_1000000Base1024=976.56[23]k t3_1048576Base1000=1048.58k "
- "t4_1048576Base1024=1024k$"},
- {"^BM_Counters_Thousands/repeats:2_median %console_report "
- "t0_1000000DefaultBase=1000k t1_1000000Base1000=1000k "
- "t2_1000000Base1024=976.56[23]k t3_1048576Base1000=1048.58k "
- "t4_1048576Base1024=1024k$"},
- {"^BM_Counters_Thousands/repeats:2_stddev %console_time_only_report [ "
- "]*2 t0_1000000DefaultBase=0 t1_1000000Base1000=0 "
- "t2_1000000Base1024=0 t3_1048576Base1000=0 t4_1048576Base1024=0$"},
- });
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Thousands/repeats:2\",$"},
- {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"repetition_index\": 0,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next},
- {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Thousands/repeats:2\",$"},
- {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next},
- {"\"run_type\": \"iteration\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"repetition_index\": 1,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"iterations\": %int,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next},
- {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Thousands/repeats:2_mean\",$"},
- {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"mean\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next},
- {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Thousands/repeats:2_median\",$"},
- {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"median\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"t0_1000000DefaultBase\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t1_1000000Base1000\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t2_1000000Base1024\": 1\\.(0)*e\\+(0)*6,$", MR_Next},
- {"\"t3_1048576Base1000\": 1\\.048576(0)*e\\+(0)*6,$", MR_Next},
- {"\"t4_1048576Base1024\": 1\\.048576(0)*e\\+(0)*6$", MR_Next},
- {"}", MR_Next}});
-ADD_CASES(TC_JSONOut,
- {{"\"name\": \"BM_Counters_Thousands/repeats:2_stddev\",$"},
- {"\"run_name\": \"BM_Counters_Thousands/repeats:2\",$", MR_Next},
- {"\"run_type\": \"aggregate\",$", MR_Next},
- {"\"repetitions\": 2,$", MR_Next},
- {"\"threads\": 1,$", MR_Next},
- {"\"aggregate_name\": \"stddev\",$", MR_Next},
- {"\"iterations\": 2,$", MR_Next},
- {"\"real_time\": %float,$", MR_Next},
- {"\"cpu_time\": %float,$", MR_Next},
- {"\"time_unit\": \"ns\",$", MR_Next},
- {"\"t0_1000000DefaultBase\": 0\\.(0)*e\\+(0)*,$", MR_Next},
- {"\"t1_1000000Base1000\": 0\\.(0)*e\\+(0)*,$", MR_Next},
- {"\"t2_1000000Base1024\": 0\\.(0)*e\\+(0)*,$", MR_Next},
- {"\"t3_1048576Base1000\": 0\\.(0)*e\\+(0)*,$", MR_Next},
- {"\"t4_1048576Base1024\": 0\\.(0)*e\\+(0)*$", MR_Next},
- {"}", MR_Next}});
-
-ADD_CASES(
- TC_CSVOut,
- {{"^\"BM_Counters_Thousands/"
- "repeats:2\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\.04858e\\+("
- "0)*6,1\\.04858e\\+(0)*6$"},
- {"^\"BM_Counters_Thousands/"
- "repeats:2\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\.04858e\\+("
- "0)*6,1\\.04858e\\+(0)*6$"},
- {"^\"BM_Counters_Thousands/"
- "repeats:2_mean\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\."
- "04858e\\+(0)*6,1\\.04858e\\+(0)*6$"},
- {"^\"BM_Counters_Thousands/"
- "repeats:2_median\",%csv_report,1e\\+(0)*6,1e\\+(0)*6,1e\\+(0)*6,1\\."
- "04858e\\+(0)*6,1\\.04858e\\+(0)*6$"},
- {"^\"BM_Counters_Thousands/repeats:2_stddev\",%csv_report,0,0,0,0,0$"}});
-// VS2013 does not allow this function to be passed as a lambda argument
-// to CHECK_BENCHMARK_RESULTS()
-void CheckThousands(Results const& e) {
- if (e.name != "BM_Counters_Thousands/repeats:2")
- return; // Do not check the aggregates!
-
- // check that the values are within 0.01% of the expected values
- CHECK_FLOAT_COUNTER_VALUE(e, "t0_1000000DefaultBase", EQ, 1000 * 1000,
- 0.0001);
- CHECK_FLOAT_COUNTER_VALUE(e, "t1_1000000Base1000", EQ, 1000 * 1000, 0.0001);
- CHECK_FLOAT_COUNTER_VALUE(e, "t2_1000000Base1024", EQ, 1000 * 1000, 0.0001);
- CHECK_FLOAT_COUNTER_VALUE(e, "t3_1048576Base1000", EQ, 1024 * 1024, 0.0001);
- CHECK_FLOAT_COUNTER_VALUE(e, "t4_1048576Base1024", EQ, 1024 * 1024, 0.0001);
-}
-CHECK_BENCHMARK_RESULTS("BM_Counters_Thousands", &CheckThousands);
-
-// ========================================================================= //
-// --------------------------- TEST CASES END ------------------------------ //
-// ========================================================================= //
-
-int main(int argc, char* argv[]) { RunOutputTests(argc, argv); }
+++ /dev/null
-#!/usr/bin/env python
-
-import unittest
-"""
-compare.py - versatile benchmark output compare tool
-"""
-
-import argparse
-from argparse import ArgumentParser
-import sys
-import gbench
-from gbench import util, report
-from gbench.util import *
-
-
-def check_inputs(in1, in2, flags):
- """
- Perform checking on the user provided inputs and diagnose any abnormalities
- """
- in1_kind, in1_err = classify_input_file(in1)
- in2_kind, in2_err = classify_input_file(in2)
- output_file = find_benchmark_flag('--benchmark_out=', flags)
- output_type = find_benchmark_flag('--benchmark_out_format=', flags)
- if in1_kind == IT_Executable and in2_kind == IT_Executable and output_file:
- print(("WARNING: '--benchmark_out=%s' will be passed to both "
- "benchmarks causing it to be overwritten") % output_file)
- if in1_kind == IT_JSON and in2_kind == IT_JSON and len(flags) > 0:
- print("WARNING: passing optional flags has no effect since both "
- "inputs are JSON")
- if output_type is not None and output_type != 'json':
- print(("ERROR: passing '--benchmark_out_format=%s' to 'compare.py`"
- " is not supported.") % output_type)
- sys.exit(1)
-
-
-def create_parser():
- parser = ArgumentParser(
- description='versatile benchmark output compare tool')
-
- parser.add_argument(
- '-a',
- '--display_aggregates_only',
- dest='display_aggregates_only',
- action="store_true",
- help="If there are repetitions, by default, we display everything - the"
- " actual runs, and the aggregates computed. Sometimes, it is "
- "desirable to only view the aggregates. E.g. when there are a lot "
- "of repetitions. Do note that only the display is affected. "
- "Internally, all the actual runs are still used, e.g. for U test.")
-
- utest = parser.add_argument_group()
- utest.add_argument(
- '--no-utest',
- dest='utest',
- default=True,
- action="store_false",
- help="The tool can do a two-tailed Mann-Whitney U test with the null hypothesis that it is equally likely that a randomly selected value from one sample will be less than or greater than a randomly selected value from a second sample.\nWARNING: requires **LARGE** (no less than {}) number of repetitions to be meaningful!\nThe test is being done by default, if at least {} repetitions were done.\nThis option can disable the U Test.".format(report.UTEST_OPTIMAL_REPETITIONS, report.UTEST_MIN_REPETITIONS))
- alpha_default = 0.05
- utest.add_argument(
- "--alpha",
- dest='utest_alpha',
- default=alpha_default,
- type=float,
- help=("significance level alpha. if the calculated p-value is below this value, then the result is said to be statistically significant and the null hypothesis is rejected.\n(default: %0.4f)") %
- alpha_default)
-
- subparsers = parser.add_subparsers(
- help='This tool has multiple modes of operation:',
- dest='mode')
-
- parser_a = subparsers.add_parser(
- 'benchmarks',
- help='The most simple use-case, compare all the output of these two benchmarks')
- baseline = parser_a.add_argument_group(
- 'baseline', 'The benchmark baseline')
- baseline.add_argument(
- 'test_baseline',
- metavar='test_baseline',
- type=argparse.FileType('r'),
- nargs=1,
- help='A benchmark executable or JSON output file')
- contender = parser_a.add_argument_group(
- 'contender', 'The benchmark that will be compared against the baseline')
- contender.add_argument(
- 'test_contender',
- metavar='test_contender',
- type=argparse.FileType('r'),
- nargs=1,
- help='A benchmark executable or JSON output file')
- parser_a.add_argument(
- 'benchmark_options',
- metavar='benchmark_options',
- nargs=argparse.REMAINDER,
- help='Arguments to pass when running benchmark executables')
-
- parser_b = subparsers.add_parser(
- 'filters', help='Compare filter one with the filter two of benchmark')
- baseline = parser_b.add_argument_group(
- 'baseline', 'The benchmark baseline')
- baseline.add_argument(
- 'test',
- metavar='test',
- type=argparse.FileType('r'),
- nargs=1,
- help='A benchmark executable or JSON output file')
- baseline.add_argument(
- 'filter_baseline',
- metavar='filter_baseline',
- type=str,
- nargs=1,
- help='The first filter, that will be used as baseline')
- contender = parser_b.add_argument_group(
- 'contender', 'The benchmark that will be compared against the baseline')
- contender.add_argument(
- 'filter_contender',
- metavar='filter_contender',
- type=str,
- nargs=1,
- help='The second filter, that will be compared against the baseline')
- parser_b.add_argument(
- 'benchmark_options',
- metavar='benchmark_options',
- nargs=argparse.REMAINDER,
- help='Arguments to pass when running benchmark executables')
-
- parser_c = subparsers.add_parser(
- 'benchmarksfiltered',
- help='Compare filter one of first benchmark with filter two of the second benchmark')
- baseline = parser_c.add_argument_group(
- 'baseline', 'The benchmark baseline')
- baseline.add_argument(
- 'test_baseline',
- metavar='test_baseline',
- type=argparse.FileType('r'),
- nargs=1,
- help='A benchmark executable or JSON output file')
- baseline.add_argument(
- 'filter_baseline',
- metavar='filter_baseline',
- type=str,
- nargs=1,
- help='The first filter, that will be used as baseline')
- contender = parser_c.add_argument_group(
- 'contender', 'The benchmark that will be compared against the baseline')
- contender.add_argument(
- 'test_contender',
- metavar='test_contender',
- type=argparse.FileType('r'),
- nargs=1,
- help='The second benchmark executable or JSON output file, that will be compared against the baseline')
- contender.add_argument(
- 'filter_contender',
- metavar='filter_contender',
- type=str,
- nargs=1,
- help='The second filter, that will be compared against the baseline')
- parser_c.add_argument(
- 'benchmark_options',
- metavar='benchmark_options',
- nargs=argparse.REMAINDER,
- help='Arguments to pass when running benchmark executables')
-
- return parser
-
-
-def main():
- # Parse the command line flags
- parser = create_parser()
- args, unknown_args = parser.parse_known_args()
- if args.mode is None:
- parser.print_help()
- exit(1)
- assert not unknown_args
- benchmark_options = args.benchmark_options
-
- if args.mode == 'benchmarks':
- test_baseline = args.test_baseline[0].name
- test_contender = args.test_contender[0].name
- filter_baseline = ''
- filter_contender = ''
-
- # NOTE: if test_baseline == test_contender, you are analyzing the stdev
-
- description = 'Comparing %s to %s' % (test_baseline, test_contender)
- elif args.mode == 'filters':
- test_baseline = args.test[0].name
- test_contender = args.test[0].name
- filter_baseline = args.filter_baseline[0]
- filter_contender = args.filter_contender[0]
-
- # NOTE: if filter_baseline == filter_contender, you are analyzing the
- # stdev
-
- description = 'Comparing %s to %s (from %s)' % (
- filter_baseline, filter_contender, args.test[0].name)
- elif args.mode == 'benchmarksfiltered':
- test_baseline = args.test_baseline[0].name
- test_contender = args.test_contender[0].name
- filter_baseline = args.filter_baseline[0]
- filter_contender = args.filter_contender[0]
-
- # NOTE: if test_baseline == test_contender and
- # filter_baseline == filter_contender, you are analyzing the stdev
-
- description = 'Comparing %s (from %s) to %s (from %s)' % (
- filter_baseline, test_baseline, filter_contender, test_contender)
- else:
- # should never happen
- print("Unrecognized mode of operation: '%s'" % args.mode)
- parser.print_help()
- exit(1)
-
- check_inputs(test_baseline, test_contender, benchmark_options)
-
- if args.display_aggregates_only:
- benchmark_options += ['--benchmark_display_aggregates_only=true']
-
- options_baseline = []
- options_contender = []
-
- if filter_baseline and filter_contender:
- options_baseline = ['--benchmark_filter=%s' % filter_baseline]
- options_contender = ['--benchmark_filter=%s' % filter_contender]
-
- # Run the benchmarks and report the results
- json1 = json1_orig = gbench.util.run_or_load_benchmark(
- test_baseline, benchmark_options + options_baseline)
- json2 = json2_orig = gbench.util.run_or_load_benchmark(
- test_contender, benchmark_options + options_contender)
-
- # Now, filter the benchmarks so that the difference report can work
- if filter_baseline and filter_contender:
- replacement = '[%s vs. %s]' % (filter_baseline, filter_contender)
- json1 = gbench.report.filter_benchmark(
- json1_orig, filter_baseline, replacement)
- json2 = gbench.report.filter_benchmark(
- json2_orig, filter_contender, replacement)
-
- # Diff and output
- output_lines = gbench.report.generate_difference_report(
- json1, json2, args.display_aggregates_only,
- args.utest, args.utest_alpha)
- print(description)
- for ln in output_lines:
- print(ln)
-
-
-class TestParser(unittest.TestCase):
- def setUp(self):
- self.parser = create_parser()
- testInputs = os.path.join(
- os.path.dirname(
- os.path.realpath(__file__)),
- 'gbench',
- 'Inputs')
- self.testInput0 = os.path.join(testInputs, 'test1_run1.json')
- self.testInput1 = os.path.join(testInputs, 'test1_run2.json')
-
- def test_benchmarks_basic(self):
- parsed = self.parser.parse_args(
- ['benchmarks', self.testInput0, self.testInput1])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertFalse(parsed.benchmark_options)
-
- def test_benchmarks_basic_without_utest(self):
- parsed = self.parser.parse_args(
- ['--no-utest', 'benchmarks', self.testInput0, self.testInput1])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertFalse(parsed.utest)
- self.assertEqual(parsed.utest_alpha, 0.05)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertFalse(parsed.benchmark_options)
-
- def test_benchmarks_basic_display_aggregates_only(self):
- parsed = self.parser.parse_args(
- ['-a', 'benchmarks', self.testInput0, self.testInput1])
- self.assertTrue(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertFalse(parsed.benchmark_options)
-
- def test_benchmarks_basic_with_utest_alpha(self):
- parsed = self.parser.parse_args(
- ['--alpha=0.314', 'benchmarks', self.testInput0, self.testInput1])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.utest_alpha, 0.314)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertFalse(parsed.benchmark_options)
-
- def test_benchmarks_basic_without_utest_with_utest_alpha(self):
- parsed = self.parser.parse_args(
- ['--no-utest', '--alpha=0.314', 'benchmarks', self.testInput0, self.testInput1])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertFalse(parsed.utest)
- self.assertEqual(parsed.utest_alpha, 0.314)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertFalse(parsed.benchmark_options)
-
- def test_benchmarks_with_remainder(self):
- parsed = self.parser.parse_args(
- ['benchmarks', self.testInput0, self.testInput1, 'd'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertEqual(parsed.benchmark_options, ['d'])
-
- def test_benchmarks_with_remainder_after_doubleminus(self):
- parsed = self.parser.parse_args(
- ['benchmarks', self.testInput0, self.testInput1, '--', 'e'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarks')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertEqual(parsed.benchmark_options, ['e'])
-
- def test_filters_basic(self):
- parsed = self.parser.parse_args(
- ['filters', self.testInput0, 'c', 'd'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'filters')
- self.assertEqual(parsed.test[0].name, self.testInput0)
- self.assertEqual(parsed.filter_baseline[0], 'c')
- self.assertEqual(parsed.filter_contender[0], 'd')
- self.assertFalse(parsed.benchmark_options)
-
- def test_filters_with_remainder(self):
- parsed = self.parser.parse_args(
- ['filters', self.testInput0, 'c', 'd', 'e'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'filters')
- self.assertEqual(parsed.test[0].name, self.testInput0)
- self.assertEqual(parsed.filter_baseline[0], 'c')
- self.assertEqual(parsed.filter_contender[0], 'd')
- self.assertEqual(parsed.benchmark_options, ['e'])
-
- def test_filters_with_remainder_after_doubleminus(self):
- parsed = self.parser.parse_args(
- ['filters', self.testInput0, 'c', 'd', '--', 'f'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'filters')
- self.assertEqual(parsed.test[0].name, self.testInput0)
- self.assertEqual(parsed.filter_baseline[0], 'c')
- self.assertEqual(parsed.filter_contender[0], 'd')
- self.assertEqual(parsed.benchmark_options, ['f'])
-
- def test_benchmarksfiltered_basic(self):
- parsed = self.parser.parse_args(
- ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarksfiltered')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.filter_baseline[0], 'c')
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertEqual(parsed.filter_contender[0], 'e')
- self.assertFalse(parsed.benchmark_options)
-
- def test_benchmarksfiltered_with_remainder(self):
- parsed = self.parser.parse_args(
- ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e', 'f'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarksfiltered')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.filter_baseline[0], 'c')
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertEqual(parsed.filter_contender[0], 'e')
- self.assertEqual(parsed.benchmark_options[0], 'f')
-
- def test_benchmarksfiltered_with_remainder_after_doubleminus(self):
- parsed = self.parser.parse_args(
- ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e', '--', 'g'])
- self.assertFalse(parsed.display_aggregates_only)
- self.assertTrue(parsed.utest)
- self.assertEqual(parsed.mode, 'benchmarksfiltered')
- self.assertEqual(parsed.test_baseline[0].name, self.testInput0)
- self.assertEqual(parsed.filter_baseline[0], 'c')
- self.assertEqual(parsed.test_contender[0].name, self.testInput1)
- self.assertEqual(parsed.filter_contender[0], 'e')
- self.assertEqual(parsed.benchmark_options[0], 'g')
-
-
-if __name__ == '__main__':
- # unittest.main()
- main()
-
-# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
-# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
-# kate: indent-mode python; remove-trailing-spaces modified;
+++ /dev/null
-{
- "context": {
- "date": "2016-08-02 17:44:46",
- "num_cpus": 4,
- "mhz_per_cpu": 4228,
- "cpu_scaling_enabled": false,
- "library_build_type": "release"
- },
- "benchmarks": [
- {
- "name": "BM_SameTimes",
- "iterations": 1000,
- "real_time": 10,
- "cpu_time": 10,
- "time_unit": "ns"
- },
- {
- "name": "BM_2xFaster",
- "iterations": 1000,
- "real_time": 50,
- "cpu_time": 50,
- "time_unit": "ns"
- },
- {
- "name": "BM_2xSlower",
- "iterations": 1000,
- "real_time": 50,
- "cpu_time": 50,
- "time_unit": "ns"
- },
- {
- "name": "BM_1PercentFaster",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_1PercentSlower",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_10PercentFaster",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_10PercentSlower",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_100xSlower",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_100xFaster",
- "iterations": 1000,
- "real_time": 10000,
- "cpu_time": 10000,
- "time_unit": "ns"
- },
- {
- "name": "BM_10PercentCPUToTime",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_ThirdFaster",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "MyComplexityTest_BigO",
- "run_name": "MyComplexityTest",
- "run_type": "aggregate",
- "aggregate_name": "BigO",
- "cpu_coefficient": 4.2749856294592886e+00,
- "real_coefficient": 6.4789275289789780e+00,
- "big_o": "N",
- "time_unit": "ns"
- },
- {
- "name": "MyComplexityTest_RMS",
- "run_name": "MyComplexityTest",
- "run_type": "aggregate",
- "aggregate_name": "RMS",
- "rms": 4.5097802512472874e-03
- },
- {
- "name": "BM_NotBadTimeUnit",
- "iterations": 1000,
- "real_time": 0.4,
- "cpu_time": 0.5,
- "time_unit": "s"
- },
- {
- "name": "BM_DifferentTimeUnit",
- "iterations": 1,
- "real_time": 1,
- "cpu_time": 1,
- "time_unit": "s"
- }
- ]
-}
+++ /dev/null
-{
- "context": {
- "date": "2016-08-02 17:44:46",
- "num_cpus": 4,
- "mhz_per_cpu": 4228,
- "cpu_scaling_enabled": false,
- "library_build_type": "release"
- },
- "benchmarks": [
- {
- "name": "BM_SameTimes",
- "iterations": 1000,
- "real_time": 10,
- "cpu_time": 10,
- "time_unit": "ns"
- },
- {
- "name": "BM_2xFaster",
- "iterations": 1000,
- "real_time": 25,
- "cpu_time": 25,
- "time_unit": "ns"
- },
- {
- "name": "BM_2xSlower",
- "iterations": 20833333,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_1PercentFaster",
- "iterations": 1000,
- "real_time": 98.9999999,
- "cpu_time": 98.9999999,
- "time_unit": "ns"
- },
- {
- "name": "BM_1PercentSlower",
- "iterations": 1000,
- "real_time": 100.9999999,
- "cpu_time": 100.9999999,
- "time_unit": "ns"
- },
- {
- "name": "BM_10PercentFaster",
- "iterations": 1000,
- "real_time": 90,
- "cpu_time": 90,
- "time_unit": "ns"
- },
- {
- "name": "BM_10PercentSlower",
- "iterations": 1000,
- "real_time": 110,
- "cpu_time": 110,
- "time_unit": "ns"
- },
- {
- "name": "BM_100xSlower",
- "iterations": 1000,
- "real_time": 1.0000e+04,
- "cpu_time": 1.0000e+04,
- "time_unit": "ns"
- },
- {
- "name": "BM_100xFaster",
- "iterations": 1000,
- "real_time": 100,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_10PercentCPUToTime",
- "iterations": 1000,
- "real_time": 110,
- "cpu_time": 90,
- "time_unit": "ns"
- },
- {
- "name": "BM_ThirdFaster",
- "iterations": 1000,
- "real_time": 66.665,
- "cpu_time": 66.664,
- "time_unit": "ns"
- },
- {
- "name": "MyComplexityTest_BigO",
- "run_name": "MyComplexityTest",
- "run_type": "aggregate",
- "aggregate_name": "BigO",
- "cpu_coefficient": 5.6215779594361486e+00,
- "real_coefficient": 5.6288314793554610e+00,
- "big_o": "N",
- "time_unit": "ns"
- },
- {
- "name": "MyComplexityTest_RMS",
- "run_name": "MyComplexityTest",
- "run_type": "aggregate",
- "aggregate_name": "RMS",
- "rms": 3.3128901852342174e-03
- },
- {
- "name": "BM_NotBadTimeUnit",
- "iterations": 1000,
- "real_time": 0.04,
- "cpu_time": 0.6,
- "time_unit": "s"
- },
- {
- "name": "BM_DifferentTimeUnit",
- "iterations": 1,
- "real_time": 1,
- "cpu_time": 1,
- "time_unit": "ns"
- }
- ]
-}
+++ /dev/null
-{
- "context": {
- "date": "2016-08-02 17:44:46",
- "num_cpus": 4,
- "mhz_per_cpu": 4228,
- "cpu_scaling_enabled": false,
- "library_build_type": "release"
- },
- "benchmarks": [
- {
- "name": "BM_Hi",
- "iterations": 1234,
- "real_time": 42,
- "cpu_time": 24,
- "time_unit": "ms"
- },
- {
- "name": "BM_Zero",
- "iterations": 1000,
- "real_time": 10,
- "cpu_time": 10,
- "time_unit": "ns"
- },
- {
- "name": "BM_Zero/4",
- "iterations": 4000,
- "real_time": 40,
- "cpu_time": 40,
- "time_unit": "ns"
- },
- {
- "name": "Prefix/BM_Zero",
- "iterations": 2000,
- "real_time": 20,
- "cpu_time": 20,
- "time_unit": "ns"
- },
- {
- "name": "Prefix/BM_Zero/3",
- "iterations": 3000,
- "real_time": 30,
- "cpu_time": 30,
- "time_unit": "ns"
- },
- {
- "name": "BM_One",
- "iterations": 5000,
- "real_time": 5,
- "cpu_time": 5,
- "time_unit": "ns"
- },
- {
- "name": "BM_One/4",
- "iterations": 2000,
- "real_time": 20,
- "cpu_time": 20,
- "time_unit": "ns"
- },
- {
- "name": "Prefix/BM_One",
- "iterations": 1000,
- "real_time": 10,
- "cpu_time": 10,
- "time_unit": "ns"
- },
- {
- "name": "Prefix/BM_One/3",
- "iterations": 1500,
- "real_time": 15,
- "cpu_time": 15,
- "time_unit": "ns"
- },
- {
- "name": "BM_Bye",
- "iterations": 5321,
- "real_time": 11,
- "cpu_time": 63,
- "time_unit": "ns"
- }
- ]
-}
+++ /dev/null
-{
- "context": {
- "date": "2016-08-02 17:44:46",
- "num_cpus": 4,
- "mhz_per_cpu": 4228,
- "cpu_scaling_enabled": false,
- "library_build_type": "release"
- },
- "benchmarks": [
- {
- "name": "BM_One",
- "run_type": "aggregate",
- "iterations": 1000,
- "real_time": 10,
- "cpu_time": 100,
- "time_unit": "ns"
- },
- {
- "name": "BM_Two",
- "iterations": 1000,
- "real_time": 9,
- "cpu_time": 90,
- "time_unit": "ns"
- },
- {
- "name": "BM_Two",
- "iterations": 1000,
- "real_time": 8,
- "cpu_time": 86,
- "time_unit": "ns"
- },
- {
- "name": "short",
- "run_type": "aggregate",
- "iterations": 1000,
- "real_time": 8,
- "cpu_time": 80,
- "time_unit": "ns"
- },
- {
- "name": "short",
- "run_type": "aggregate",
- "iterations": 1000,
- "real_time": 8,
- "cpu_time": 77,
- "time_unit": "ns"
- },
- {
- "name": "medium",
- "run_type": "iteration",
- "iterations": 1000,
- "real_time": 8,
- "cpu_time": 80,
- "time_unit": "ns"
- },
- {
- "name": "medium",
- "run_type": "iteration",
- "iterations": 1000,
- "real_time": 9,
- "cpu_time": 82,
- "time_unit": "ns"
- }
- ]
-}
+++ /dev/null
-{
- "context": {
- "date": "2016-08-02 17:44:46",
- "num_cpus": 4,
- "mhz_per_cpu": 4228,
- "cpu_scaling_enabled": false,
- "library_build_type": "release"
- },
- "benchmarks": [
- {
- "name": "BM_One",
- "iterations": 1000,
- "real_time": 9,
- "cpu_time": 110,
- "time_unit": "ns"
- },
- {
- "name": "BM_Two",
- "run_type": "aggregate",
- "iterations": 1000,
- "real_time": 10,
- "cpu_time": 89,
- "time_unit": "ns"
- },
- {
- "name": "BM_Two",
- "iterations": 1000,
- "real_time": 7,
- "cpu_time": 72,
- "time_unit": "ns"
- },
- {
- "name": "short",
- "run_type": "aggregate",
- "iterations": 1000,
- "real_time": 7,
- "cpu_time": 75,
- "time_unit": "ns"
- },
- {
- "name": "short",
- "run_type": "aggregate",
- "iterations": 762,
- "real_time": 4.54,
- "cpu_time": 66.6,
- "time_unit": "ns"
- },
- {
- "name": "short",
- "run_type": "iteration",
- "iterations": 1000,
- "real_time": 800,
- "cpu_time": 1,
- "time_unit": "ns"
- },
- {
- "name": "medium",
- "run_type": "iteration",
- "iterations": 1200,
- "real_time": 5,
- "cpu_time": 53,
- "time_unit": "ns"
- }
- ]
-}
+++ /dev/null
-"""Google Benchmark tooling"""
-
-__author__ = 'Eric Fiselier'
-__email__ = 'eric@efcs.ca'
-__versioninfo__ = (0, 5, 0)
-__version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev'
-
-__all__ = []
+++ /dev/null
-import unittest
-"""report.py - Utilities for reporting statistics about benchmark results
-"""
-import os
-import re
-import copy
-
-from scipy.stats import mannwhitneyu
-
-
-class BenchmarkColor(object):
- def __init__(self, name, code):
- self.name = name
- self.code = code
-
- def __repr__(self):
- return '%s%r' % (self.__class__.__name__,
- (self.name, self.code))
-
- def __format__(self, format):
- return self.code
-
-
-# Benchmark Colors Enumeration
-BC_NONE = BenchmarkColor('NONE', '')
-BC_MAGENTA = BenchmarkColor('MAGENTA', '\033[95m')
-BC_CYAN = BenchmarkColor('CYAN', '\033[96m')
-BC_OKBLUE = BenchmarkColor('OKBLUE', '\033[94m')
-BC_OKGREEN = BenchmarkColor('OKGREEN', '\033[32m')
-BC_HEADER = BenchmarkColor('HEADER', '\033[92m')
-BC_WARNING = BenchmarkColor('WARNING', '\033[93m')
-BC_WHITE = BenchmarkColor('WHITE', '\033[97m')
-BC_FAIL = BenchmarkColor('FAIL', '\033[91m')
-BC_ENDC = BenchmarkColor('ENDC', '\033[0m')
-BC_BOLD = BenchmarkColor('BOLD', '\033[1m')
-BC_UNDERLINE = BenchmarkColor('UNDERLINE', '\033[4m')
-
-UTEST_MIN_REPETITIONS = 2
-UTEST_OPTIMAL_REPETITIONS = 9 # Lowest reasonable number, More is better.
-UTEST_COL_NAME = "_pvalue"
-
-
-def color_format(use_color, fmt_str, *args, **kwargs):
- """
- Return the result of 'fmt_str.format(*args, **kwargs)' after transforming
- 'args' and 'kwargs' according to the value of 'use_color'. If 'use_color'
- is False then all color codes in 'args' and 'kwargs' are replaced with
- the empty string.
- """
- assert use_color is True or use_color is False
- if not use_color:
- args = [arg if not isinstance(arg, BenchmarkColor) else BC_NONE
- for arg in args]
- kwargs = {key: arg if not isinstance(arg, BenchmarkColor) else BC_NONE
- for key, arg in kwargs.items()}
- return fmt_str.format(*args, **kwargs)
-
-
-def find_longest_name(benchmark_list):
- """
- Return the length of the longest benchmark name in a given list of
- benchmark JSON objects
- """
- longest_name = 1
- for bc in benchmark_list:
- if len(bc['name']) > longest_name:
- longest_name = len(bc['name'])
- return longest_name
-
-
-def calculate_change(old_val, new_val):
- """
- Return a float representing the decimal change between old_val and new_val.
- """
- if old_val == 0 and new_val == 0:
- return 0.0
- if old_val == 0:
- return float(new_val - old_val) / (float(old_val + new_val) / 2)
- return float(new_val - old_val) / abs(old_val)
-
-
-def filter_benchmark(json_orig, family, replacement=""):
- """
- Apply a filter to the json, and only leave the 'family' of benchmarks.
- """
- regex = re.compile(family)
- filtered = {}
- filtered['benchmarks'] = []
- for be in json_orig['benchmarks']:
- if not regex.search(be['name']):
- continue
- filteredbench = copy.deepcopy(be) # Do NOT modify the old name!
- filteredbench['name'] = regex.sub(replacement, filteredbench['name'])
- filtered['benchmarks'].append(filteredbench)
- return filtered
-
-
-def get_unique_benchmark_names(json):
- """
- While *keeping* the order, give all the unique 'names' used for benchmarks.
- """
- seen = set()
- uniqued = [x['name'] for x in json['benchmarks']
- if x['name'] not in seen and
- (seen.add(x['name']) or True)]
- return uniqued
-
-
-def intersect(list1, list2):
- """
- Given two lists, get a new list consisting of the elements only contained
- in *both of the input lists*, while preserving the ordering.
- """
- return [x for x in list1 if x in list2]
-
-
-def is_potentially_comparable_benchmark(x):
- return ('time_unit' in x and 'real_time' in x and 'cpu_time' in x)
-
-
-def partition_benchmarks(json1, json2):
- """
- While preserving the ordering, find benchmarks with the same names in
- both of the inputs, and group them.
- (i.e. partition/filter into groups with common name)
- """
- json1_unique_names = get_unique_benchmark_names(json1)
- json2_unique_names = get_unique_benchmark_names(json2)
- names = intersect(json1_unique_names, json2_unique_names)
- partitions = []
- for name in names:
- time_unit = None
- # Pick the time unit from the first entry of the lhs benchmark.
- # We should be careful not to crash with unexpected input.
- for x in json1['benchmarks']:
- if (x['name'] == name and is_potentially_comparable_benchmark(x)):
- time_unit = x['time_unit']
- break
- if time_unit is None:
- continue
- # Filter by name and time unit.
- # All the repetitions are assumed to be comparable.
- lhs = [x for x in json1['benchmarks'] if x['name'] == name and
- x['time_unit'] == time_unit]
- rhs = [x for x in json2['benchmarks'] if x['name'] == name and
- x['time_unit'] == time_unit]
- partitions.append([lhs, rhs])
- return partitions
-
-
-def extract_field(partition, field_name):
- # The count of elements may be different. We want *all* of them.
- lhs = [x[field_name] for x in partition[0]]
- rhs = [x[field_name] for x in partition[1]]
- return [lhs, rhs]
-
-def calc_utest(timings_cpu, timings_time):
- min_rep_cnt = min(len(timings_time[0]),
- len(timings_time[1]),
- len(timings_cpu[0]),
- len(timings_cpu[1]))
-
- # Does *everything* has at least UTEST_MIN_REPETITIONS repetitions?
- if min_rep_cnt < UTEST_MIN_REPETITIONS:
- return False, None, None
-
- time_pvalue = mannwhitneyu(
- timings_time[0], timings_time[1], alternative='two-sided').pvalue
- cpu_pvalue = mannwhitneyu(
- timings_cpu[0], timings_cpu[1], alternative='two-sided').pvalue
-
- return (min_rep_cnt >= UTEST_OPTIMAL_REPETITIONS), cpu_pvalue, time_pvalue
-
-def print_utest(partition, utest_alpha, first_col_width, use_color=True):
- def get_utest_color(pval):
- return BC_FAIL if pval >= utest_alpha else BC_OKGREEN
-
- timings_time = extract_field(partition, 'real_time')
- timings_cpu = extract_field(partition, 'cpu_time')
- have_optimal_repetitions, cpu_pvalue, time_pvalue = calc_utest(timings_cpu, timings_time)
-
- # Check if we failed miserably with minimum required repetitions for utest
- if not have_optimal_repetitions and cpu_pvalue is None and time_pvalue is None:
- return []
-
- dsc = "U Test, Repetitions: {} vs {}".format(
- len(timings_cpu[0]), len(timings_cpu[1]))
- dsc_color = BC_OKGREEN
-
- # We still got some results to show but issue a warning about it.
- if not have_optimal_repetitions:
- dsc_color = BC_WARNING
- dsc += ". WARNING: Results unreliable! {}+ repetitions recommended.".format(
- UTEST_OPTIMAL_REPETITIONS)
-
- special_str = "{}{:<{}s}{endc}{}{:16.4f}{endc}{}{:16.4f}{endc}{} {}"
-
- last_name = partition[0][0]['name']
- return [color_format(use_color,
- special_str,
- BC_HEADER,
- "{}{}".format(last_name, UTEST_COL_NAME),
- first_col_width,
- get_utest_color(time_pvalue), time_pvalue,
- get_utest_color(cpu_pvalue), cpu_pvalue,
- dsc_color, dsc,
- endc=BC_ENDC)]
-
-
-def generate_difference_report(
- json1,
- json2,
- display_aggregates_only=False,
- utest=False,
- utest_alpha=0.05,
- use_color=True):
- """
- Calculate and report the difference between each test of two benchmarks
- runs specified as 'json1' and 'json2'.
- """
- assert utest is True or utest is False
- first_col_width = find_longest_name(json1['benchmarks'])
-
- def find_test(name):
- for b in json2['benchmarks']:
- if b['name'] == name:
- return b
- return None
-
- first_col_width = max(
- first_col_width,
- len('Benchmark'))
- first_col_width += len(UTEST_COL_NAME)
- first_line = "{:<{}s}Time CPU Time Old Time New CPU Old CPU New".format(
- 'Benchmark', 12 + first_col_width)
- output_strs = [first_line, '-' * len(first_line)]
-
- partitions = partition_benchmarks(json1, json2)
- for partition in partitions:
- # Careful, we may have different repetition count.
- for i in range(min(len(partition[0]), len(partition[1]))):
- bn = partition[0][i]
- other_bench = partition[1][i]
-
- # *If* we were asked to only display aggregates,
- # and if it is non-aggregate, then skip it.
- if display_aggregates_only and 'run_type' in bn and 'run_type' in other_bench:
- assert bn['run_type'] == other_bench['run_type']
- if bn['run_type'] != 'aggregate':
- continue
-
- fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}"
-
- def get_color(res):
- if res > 0.05:
- return BC_FAIL
- elif res > -0.07:
- return BC_WHITE
- else:
- return BC_CYAN
-
- tres = calculate_change(bn['real_time'], other_bench['real_time'])
- cpures = calculate_change(bn['cpu_time'], other_bench['cpu_time'])
- output_strs += [color_format(use_color,
- fmt_str,
- BC_HEADER,
- bn['name'],
- first_col_width,
- get_color(tres),
- tres,
- get_color(cpures),
- cpures,
- bn['real_time'],
- other_bench['real_time'],
- bn['cpu_time'],
- other_bench['cpu_time'],
- endc=BC_ENDC)]
-
- # After processing the whole partition, if requested, do the U test.
- if utest:
- output_strs += print_utest(partition,
- utest_alpha=utest_alpha,
- first_col_width=first_col_width,
- use_color=use_color)
-
- return output_strs
-
-
-###############################################################################
-# Unit tests
-
-
-class TestGetUniqueBenchmarkNames(unittest.TestCase):
- def load_results(self):
- import json
- testInputs = os.path.join(
- os.path.dirname(
- os.path.realpath(__file__)),
- 'Inputs')
- testOutput = os.path.join(testInputs, 'test3_run0.json')
- with open(testOutput, 'r') as f:
- json = json.load(f)
- return json
-
- def test_basic(self):
- expect_lines = [
- 'BM_One',
- 'BM_Two',
- 'short', # These two are not sorted
- 'medium', # These two are not sorted
- ]
- json = self.load_results()
- output_lines = get_unique_benchmark_names(json)
- print("\n")
- print("\n".join(output_lines))
- self.assertEqual(len(output_lines), len(expect_lines))
- for i in range(0, len(output_lines)):
- self.assertEqual(expect_lines[i], output_lines[i])
-
-
-class TestReportDifference(unittest.TestCase):
- def load_results(self):
- import json
- testInputs = os.path.join(
- os.path.dirname(
- os.path.realpath(__file__)),
- 'Inputs')
- testOutput1 = os.path.join(testInputs, 'test1_run1.json')
- testOutput2 = os.path.join(testInputs, 'test1_run2.json')
- with open(testOutput1, 'r') as f:
- json1 = json.load(f)
- with open(testOutput2, 'r') as f:
- json2 = json.load(f)
- return json1, json2
-
- def test_basic(self):
- expect_lines = [
- ['BM_SameTimes', '+0.0000', '+0.0000', '10', '10', '10', '10'],
- ['BM_2xFaster', '-0.5000', '-0.5000', '50', '25', '50', '25'],
- ['BM_2xSlower', '+1.0000', '+1.0000', '50', '100', '50', '100'],
- ['BM_1PercentFaster', '-0.0100', '-0.0100', '100', '99', '100', '99'],
- ['BM_1PercentSlower', '+0.0100', '+0.0100', '100', '101', '100', '101'],
- ['BM_10PercentFaster', '-0.1000', '-0.1000', '100', '90', '100', '90'],
- ['BM_10PercentSlower', '+0.1000', '+0.1000', '100', '110', '100', '110'],
- ['BM_100xSlower', '+99.0000', '+99.0000',
- '100', '10000', '100', '10000'],
- ['BM_100xFaster', '-0.9900', '-0.9900',
- '10000', '100', '10000', '100'],
- ['BM_10PercentCPUToTime', '+0.1000',
- '-0.1000', '100', '110', '100', '90'],
- ['BM_ThirdFaster', '-0.3333', '-0.3334', '100', '67', '100', '67'],
- ['BM_NotBadTimeUnit', '-0.9000', '+0.2000', '0', '0', '0', '1'],
- ]
- json1, json2 = self.load_results()
- output_lines_with_header = generate_difference_report(
- json1, json2, use_color=False)
- output_lines = output_lines_with_header[2:]
- print("\n")
- print("\n".join(output_lines_with_header))
- self.assertEqual(len(output_lines), len(expect_lines))
- for i in range(0, len(output_lines)):
- parts = [x for x in output_lines[i].split(' ') if x]
- self.assertEqual(len(parts), 7)
- self.assertEqual(expect_lines[i], parts)
-
-
-class TestReportDifferenceBetweenFamilies(unittest.TestCase):
- def load_result(self):
- import json
- testInputs = os.path.join(
- os.path.dirname(
- os.path.realpath(__file__)),
- 'Inputs')
- testOutput = os.path.join(testInputs, 'test2_run.json')
- with open(testOutput, 'r') as f:
- json = json.load(f)
- return json
-
- def test_basic(self):
- expect_lines = [
- ['.', '-0.5000', '-0.5000', '10', '5', '10', '5'],
- ['./4', '-0.5000', '-0.5000', '40', '20', '40', '20'],
- ['Prefix/.', '-0.5000', '-0.5000', '20', '10', '20', '10'],
- ['Prefix/./3', '-0.5000', '-0.5000', '30', '15', '30', '15'],
- ]
- json = self.load_result()
- json1 = filter_benchmark(json, "BM_Z.ro", ".")
- json2 = filter_benchmark(json, "BM_O.e", ".")
- output_lines_with_header = generate_difference_report(
- json1, json2, use_color=False)
- output_lines = output_lines_with_header[2:]
- print("\n")
- print("\n".join(output_lines_with_header))
- self.assertEqual(len(output_lines), len(expect_lines))
- for i in range(0, len(output_lines)):
- parts = [x for x in output_lines[i].split(' ') if x]
- self.assertEqual(len(parts), 7)
- self.assertEqual(expect_lines[i], parts)
-
-
-class TestReportDifferenceWithUTest(unittest.TestCase):
- def load_results(self):
- import json
- testInputs = os.path.join(
- os.path.dirname(
- os.path.realpath(__file__)),
- 'Inputs')
- testOutput1 = os.path.join(testInputs, 'test3_run0.json')
- testOutput2 = os.path.join(testInputs, 'test3_run1.json')
- with open(testOutput1, 'r') as f:
- json1 = json.load(f)
- with open(testOutput2, 'r') as f:
- json2 = json.load(f)
- return json1, json2
-
- def test_utest(self):
- expect_lines = []
- expect_lines = [
- ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'],
- ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'],
- ['BM_Two', '-0.1250', '-0.1628', '8', '7', '86', '72'],
- ['BM_Two_pvalue',
- '0.6985',
- '0.6985',
- 'U',
- 'Test,',
- 'Repetitions:',
- '2',
- 'vs',
- '2.',
- 'WARNING:',
- 'Results',
- 'unreliable!',
- '9+',
- 'repetitions',
- 'recommended.'],
- ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'],
- ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'],
- ['short_pvalue',
- '0.7671',
- '0.1489',
- 'U',
- 'Test,',
- 'Repetitions:',
- '2',
- 'vs',
- '3.',
- 'WARNING:',
- 'Results',
- 'unreliable!',
- '9+',
- 'repetitions',
- 'recommended.'],
- ['medium', '-0.3750', '-0.3375', '8', '5', '80', '53'],
- ]
- json1, json2 = self.load_results()
- output_lines_with_header = generate_difference_report(
- json1, json2, utest=True, utest_alpha=0.05, use_color=False)
- output_lines = output_lines_with_header[2:]
- print("\n")
- print("\n".join(output_lines_with_header))
- self.assertEqual(len(output_lines), len(expect_lines))
- for i in range(0, len(output_lines)):
- parts = [x for x in output_lines[i].split(' ') if x]
- self.assertEqual(expect_lines[i], parts)
-
-
-class TestReportDifferenceWithUTestWhileDisplayingAggregatesOnly(
- unittest.TestCase):
- def load_results(self):
- import json
- testInputs = os.path.join(
- os.path.dirname(
- os.path.realpath(__file__)),
- 'Inputs')
- testOutput1 = os.path.join(testInputs, 'test3_run0.json')
- testOutput2 = os.path.join(testInputs, 'test3_run1.json')
- with open(testOutput1, 'r') as f:
- json1 = json.load(f)
- with open(testOutput2, 'r') as f:
- json2 = json.load(f)
- return json1, json2
-
- def test_utest(self):
- expect_lines = []
- expect_lines = [
- ['BM_One', '-0.1000', '+0.1000', '10', '9', '100', '110'],
- ['BM_Two', '+0.1111', '-0.0111', '9', '10', '90', '89'],
- ['BM_Two', '-0.1250', '-0.1628', '8', '7', '86', '72'],
- ['BM_Two_pvalue',
- '0.6985',
- '0.6985',
- 'U',
- 'Test,',
- 'Repetitions:',
- '2',
- 'vs',
- '2.',
- 'WARNING:',
- 'Results',
- 'unreliable!',
- '9+',
- 'repetitions',
- 'recommended.'],
- ['short', '-0.1250', '-0.0625', '8', '7', '80', '75'],
- ['short', '-0.4325', '-0.1351', '8', '5', '77', '67'],
- ['short_pvalue',
- '0.7671',
- '0.1489',
- 'U',
- 'Test,',
- 'Repetitions:',
- '2',
- 'vs',
- '3.',
- 'WARNING:',
- 'Results',
- 'unreliable!',
- '9+',
- 'repetitions',
- 'recommended.'],
- ]
- json1, json2 = self.load_results()
- output_lines_with_header = generate_difference_report(
- json1, json2, display_aggregates_only=True,
- utest=True, utest_alpha=0.05, use_color=False)
- output_lines = output_lines_with_header[2:]
- print("\n")
- print("\n".join(output_lines_with_header))
- self.assertEqual(len(output_lines), len(expect_lines))
- for i in range(0, len(output_lines)):
- parts = [x for x in output_lines[i].split(' ') if x]
- self.assertEqual(expect_lines[i], parts)
-
-
-if __name__ == '__main__':
- unittest.main()
-
-# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
-# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
-# kate: indent-mode python; remove-trailing-spaces modified;
+++ /dev/null
-"""util.py - General utilities for running, loading, and processing benchmarks
-"""
-import json
-import os
-import tempfile
-import subprocess
-import sys
-
-# Input file type enumeration
-IT_Invalid = 0
-IT_JSON = 1
-IT_Executable = 2
-
-_num_magic_bytes = 2 if sys.platform.startswith('win') else 4
-
-
-def is_executable_file(filename):
- """
- Return 'True' if 'filename' names a valid file which is likely
- an executable. A file is considered an executable if it starts with the
- magic bytes for a EXE, Mach O, or ELF file.
- """
- if not os.path.isfile(filename):
- return False
- with open(filename, mode='rb') as f:
- magic_bytes = f.read(_num_magic_bytes)
- if sys.platform == 'darwin':
- return magic_bytes in [
- b'\xfe\xed\xfa\xce', # MH_MAGIC
- b'\xce\xfa\xed\xfe', # MH_CIGAM
- b'\xfe\xed\xfa\xcf', # MH_MAGIC_64
- b'\xcf\xfa\xed\xfe', # MH_CIGAM_64
- b'\xca\xfe\xba\xbe', # FAT_MAGIC
- b'\xbe\xba\xfe\xca' # FAT_CIGAM
- ]
- elif sys.platform.startswith('win'):
- return magic_bytes == b'MZ'
- else:
- return magic_bytes == b'\x7FELF'
-
-
-def is_json_file(filename):
- """
- Returns 'True' if 'filename' names a valid JSON output file.
- 'False' otherwise.
- """
- try:
- with open(filename, 'r') as f:
- json.load(f)
- return True
- except BaseException:
- pass
- return False
-
-
-def classify_input_file(filename):
- """
- Return a tuple (type, msg) where 'type' specifies the classified type
- of 'filename'. If 'type' is 'IT_Invalid' then 'msg' is a human readable
- string represeting the error.
- """
- ftype = IT_Invalid
- err_msg = None
- if not os.path.exists(filename):
- err_msg = "'%s' does not exist" % filename
- elif not os.path.isfile(filename):
- err_msg = "'%s' does not name a file" % filename
- elif is_executable_file(filename):
- ftype = IT_Executable
- elif is_json_file(filename):
- ftype = IT_JSON
- else:
- err_msg = "'%s' does not name a valid benchmark executable or JSON file" % filename
- return ftype, err_msg
-
-
-def check_input_file(filename):
- """
- Classify the file named by 'filename' and return the classification.
- If the file is classified as 'IT_Invalid' print an error message and exit
- the program.
- """
- ftype, msg = classify_input_file(filename)
- if ftype == IT_Invalid:
- print("Invalid input file: %s" % msg)
- sys.exit(1)
- return ftype
-
-
-def find_benchmark_flag(prefix, benchmark_flags):
- """
- Search the specified list of flags for a flag matching `<prefix><arg>` and
- if it is found return the arg it specifies. If specified more than once the
- last value is returned. If the flag is not found None is returned.
- """
- assert prefix.startswith('--') and prefix.endswith('=')
- result = None
- for f in benchmark_flags:
- if f.startswith(prefix):
- result = f[len(prefix):]
- return result
-
-
-def remove_benchmark_flags(prefix, benchmark_flags):
- """
- Return a new list containing the specified benchmark_flags except those
- with the specified prefix.
- """
- assert prefix.startswith('--') and prefix.endswith('=')
- return [f for f in benchmark_flags if not f.startswith(prefix)]
-
-
-def load_benchmark_results(fname):
- """
- Read benchmark output from a file and return the JSON object.
- REQUIRES: 'fname' names a file containing JSON benchmark output.
- """
- with open(fname, 'r') as f:
- return json.load(f)
-
-
-def run_benchmark(exe_name, benchmark_flags):
- """
- Run a benchmark specified by 'exe_name' with the specified
- 'benchmark_flags'. The benchmark is run directly as a subprocess to preserve
- real time console output.
- RETURNS: A JSON object representing the benchmark output
- """
- output_name = find_benchmark_flag('--benchmark_out=',
- benchmark_flags)
- is_temp_output = False
- if output_name is None:
- is_temp_output = True
- thandle, output_name = tempfile.mkstemp()
- os.close(thandle)
- benchmark_flags = list(benchmark_flags) + \
- ['--benchmark_out=%s' % output_name]
-
- cmd = [exe_name] + benchmark_flags
- print("RUNNING: %s" % ' '.join(cmd))
- exitCode = subprocess.call(cmd)
- if exitCode != 0:
- print('TEST FAILED...')
- sys.exit(exitCode)
- json_res = load_benchmark_results(output_name)
- if is_temp_output:
- os.unlink(output_name)
- return json_res
-
-
-def run_or_load_benchmark(filename, benchmark_flags):
- """
- Get the results for a specified benchmark. If 'filename' specifies
- an executable benchmark then the results are generated by running the
- benchmark. Otherwise 'filename' must name a valid JSON output file,
- which is loaded and the result returned.
- """
- ftype = check_input_file(filename)
- if ftype == IT_JSON:
- return load_benchmark_results(filename)
- elif ftype == IT_Executable:
- return run_benchmark(filename, benchmark_flags)
- else:
- assert False # This branch is unreachable
+++ /dev/null
-#!/usr/bin/env python
-
-"""
-strip_asm.py - Cleanup ASM output for the specified file
-"""
-
-from argparse import ArgumentParser
-import sys
-import os
-import re
-
-def find_used_labels(asm):
- found = set()
- label_re = re.compile("\s*j[a-z]+\s+\.L([a-zA-Z0-9][a-zA-Z0-9_]*)")
- for l in asm.splitlines():
- m = label_re.match(l)
- if m:
- found.add('.L%s' % m.group(1))
- return found
-
-
-def normalize_labels(asm):
- decls = set()
- label_decl = re.compile("^[.]{0,1}L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)")
- for l in asm.splitlines():
- m = label_decl.match(l)
- if m:
- decls.add(m.group(0))
- if len(decls) == 0:
- return asm
- needs_dot = next(iter(decls))[0] != '.'
- if not needs_dot:
- return asm
- for ld in decls:
- asm = re.sub("(^|\s+)" + ld + "(?=:|\s)", '\\1.' + ld, asm)
- return asm
-
-
-def transform_labels(asm):
- asm = normalize_labels(asm)
- used_decls = find_used_labels(asm)
- new_asm = ''
- label_decl = re.compile("^\.L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)")
- for l in asm.splitlines():
- m = label_decl.match(l)
- if not m or m.group(0) in used_decls:
- new_asm += l
- new_asm += '\n'
- return new_asm
-
-
-def is_identifier(tk):
- if len(tk) == 0:
- return False
- first = tk[0]
- if not first.isalpha() and first != '_':
- return False
- for i in range(1, len(tk)):
- c = tk[i]
- if not c.isalnum() and c != '_':
- return False
- return True
-
-def process_identifiers(l):
- """
- process_identifiers - process all identifiers and modify them to have
- consistent names across all platforms; specifically across ELF and MachO.
- For example, MachO inserts an additional understore at the beginning of
- names. This function removes that.
- """
- parts = re.split(r'([a-zA-Z0-9_]+)', l)
- new_line = ''
- for tk in parts:
- if is_identifier(tk):
- if tk.startswith('__Z'):
- tk = tk[1:]
- elif tk.startswith('_') and len(tk) > 1 and \
- tk[1].isalpha() and tk[1] != 'Z':
- tk = tk[1:]
- new_line += tk
- return new_line
-
-
-def process_asm(asm):
- """
- Strip the ASM of unwanted directives and lines
- """
- new_contents = ''
- asm = transform_labels(asm)
-
- # TODO: Add more things we want to remove
- discard_regexes = [
- re.compile("\s+\..*$"), # directive
- re.compile("\s*#(NO_APP|APP)$"), #inline ASM
- re.compile("\s*#.*$"), # comment line
- re.compile("\s*\.globa?l\s*([.a-zA-Z_][a-zA-Z0-9$_.]*)"), #global directive
- re.compile("\s*\.(string|asciz|ascii|[1248]?byte|short|word|long|quad|value|zero)"),
- ]
- keep_regexes = [
-
- ]
- fn_label_def = re.compile("^[a-zA-Z_][a-zA-Z0-9_.]*:")
- for l in asm.splitlines():
- # Remove Mach-O attribute
- l = l.replace('@GOTPCREL', '')
- add_line = True
- for reg in discard_regexes:
- if reg.match(l) is not None:
- add_line = False
- break
- for reg in keep_regexes:
- if reg.match(l) is not None:
- add_line = True
- break
- if add_line:
- if fn_label_def.match(l) and len(new_contents) != 0:
- new_contents += '\n'
- l = process_identifiers(l)
- new_contents += l
- new_contents += '\n'
- return new_contents
-
-def main():
- parser = ArgumentParser(
- description='generate a stripped assembly file')
- parser.add_argument(
- 'input', metavar='input', type=str, nargs=1,
- help='An input assembly file')
- parser.add_argument(
- 'out', metavar='output', type=str, nargs=1,
- help='The output file')
- args, unknown_args = parser.parse_known_args()
- input = args.input[0]
- output = args.out[0]
- if not os.path.isfile(input):
- print(("ERROR: input file '%s' does not exist") % input)
- sys.exit(1)
- contents = None
- with open(input, 'r') as f:
- contents = f.read()
- new_contents = process_asm(contents)
- with open(output, 'w') as f:
- f.write(new_contents)
-
-
-if __name__ == '__main__':
- main()
-
-# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
-# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off;
-# kate: indent-mode python; remove-trailing-spaces modified;
+++ /dev/null
-########################################################################
-# Note: CMake support is community-based. The maintainers do not use CMake
-# internally.
-#
-# CMake build script for Google Test.
-#
-# To run the tests for Google Test itself on Linux, use 'make test' or
-# ctest. You can select which tests to run using 'ctest -R regex'.
-# For more options, run 'ctest --help'.
-
-# When other libraries are using a shared version of runtime libraries,
-# Google Test also has to use one.
-option(
- gtest_force_shared_crt
- "Use shared (DLL) run-time lib even when Google Test is built as static lib."
- OFF)
-
-option(gtest_build_tests "Build all of gtest's own tests." OFF)
-
-option(gtest_build_samples "Build gtest's sample programs." OFF)
-
-option(gtest_disable_pthreads "Disable uses of pthreads in gtest." OFF)
-
-option(
- gtest_hide_internal_symbols
- "Build gtest with internal symbols hidden in shared libraries."
- OFF)
-
-# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build().
-include(cmake/hermetic_build.cmake OPTIONAL)
-
-if (COMMAND pre_project_set_up_hermetic_build)
- pre_project_set_up_hermetic_build()
-endif()
-
-########################################################################
-#
-# Project-wide settings
-
-# Name of the project.
-#
-# CMake files in this project can refer to the root source directory
-# as ${gtest_SOURCE_DIR} and to the root binary directory as
-# ${gtest_BINARY_DIR}.
-# Language "C" is required for find_package(Threads).
-
-# Project version:
-
-if (CMAKE_VERSION VERSION_LESS 3.0)
- project(gtest CXX C)
- set(PROJECT_VERSION ${GOOGLETEST_VERSION})
-else()
- cmake_policy(SET CMP0048 NEW)
- project(gtest VERSION ${GOOGLETEST_VERSION} LANGUAGES CXX C)
-endif()
-cmake_minimum_required(VERSION 2.6.4)
-
-if (POLICY CMP0063) # Visibility
- cmake_policy(SET CMP0063 NEW)
-endif (POLICY CMP0063)
-
-if (COMMAND set_up_hermetic_build)
- set_up_hermetic_build()
-endif()
-
-# These commands only run if this is the main project
-if(CMAKE_PROJECT_NAME STREQUAL "gtest" OR CMAKE_PROJECT_NAME STREQUAL "googletest-distribution")
-
- # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to
- # make it prominent in the GUI.
- option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF)
-
-else()
-
- mark_as_advanced(
- gtest_force_shared_crt
- gtest_build_tests
- gtest_build_samples
- gtest_disable_pthreads
- gtest_hide_internal_symbols)
-
-endif()
-
-
-if (gtest_hide_internal_symbols)
- set(CMAKE_CXX_VISIBILITY_PRESET hidden)
- set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
-endif()
-
-# Define helper functions and macros used by Google Test.
-include(cmake/internal_utils.cmake)
-
-config_compiler_and_linker() # Defined in internal_utils.cmake.
-
-# Create the CMake package file descriptors.
-if (INSTALL_GTEST)
- include(CMakePackageConfigHelpers)
- set(cmake_package_name GTest)
- set(targets_export_name ${cmake_package_name}Targets CACHE INTERNAL "")
- set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated" CACHE INTERNAL "")
- set(cmake_files_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${cmake_package_name}")
- set(version_file "${generated_dir}/${cmake_package_name}ConfigVersion.cmake")
- write_basic_package_version_file(${version_file} VERSION ${GOOGLETEST_VERSION} COMPATIBILITY AnyNewerVersion)
- install(EXPORT ${targets_export_name}
- NAMESPACE ${cmake_package_name}::
- DESTINATION ${cmake_files_install_dir})
- set(config_file "${generated_dir}/${cmake_package_name}Config.cmake")
- configure_package_config_file("${gtest_SOURCE_DIR}/cmake/Config.cmake.in"
- "${config_file}" INSTALL_DESTINATION ${cmake_files_install_dir})
- install(FILES ${version_file} ${config_file}
- DESTINATION ${cmake_files_install_dir})
-endif()
-
-# Where Google Test's .h files can be found.
-set(gtest_build_include_dirs
- "${gtest_SOURCE_DIR}/include"
- "${gtest_SOURCE_DIR}")
-include_directories(${gtest_build_include_dirs})
-
-########################################################################
-#
-# Defines the gtest & gtest_main libraries. User tests should link
-# with one of them.
-
-# Google Test libraries. We build them using more strict warnings than what
-# are used for other targets, to ensure that gtest can be compiled by a user
-# aggressive about warnings.
-cxx_library(gtest "${cxx_strict}" src/gtest-all.cc)
-cxx_library(gtest_main "${cxx_strict}" src/gtest_main.cc)
-# If the CMake version supports it, attach header directory information
-# to the targets for when we are part of a parent build (ie being pulled
-# in via add_subdirectory() rather than being a standalone build).
-if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
- target_include_directories(gtest SYSTEM INTERFACE
- "$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
- "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
- target_include_directories(gtest_main SYSTEM INTERFACE
- "$<BUILD_INTERFACE:${gtest_build_include_dirs}>"
- "$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>")
-endif()
-target_link_libraries(gtest_main PUBLIC gtest)
-
-########################################################################
-#
-# Install rules
-install_project(gtest gtest_main)
-
-########################################################################
-#
-# Samples on how to link user tests with gtest or gtest_main.
-#
-# They are not built by default. To build them, set the
-# gtest_build_samples option to ON. You can do it by running ccmake
-# or specifying the -Dgtest_build_samples=ON flag when running cmake.
-
-if (gtest_build_samples)
- cxx_executable(sample1_unittest samples gtest_main samples/sample1.cc)
- cxx_executable(sample2_unittest samples gtest_main samples/sample2.cc)
- cxx_executable(sample3_unittest samples gtest_main)
- cxx_executable(sample4_unittest samples gtest_main samples/sample4.cc)
- cxx_executable(sample5_unittest samples gtest_main samples/sample1.cc)
- cxx_executable(sample6_unittest samples gtest_main)
- cxx_executable(sample7_unittest samples gtest_main)
- cxx_executable(sample8_unittest samples gtest_main)
- cxx_executable(sample9_unittest samples gtest)
- cxx_executable(sample10_unittest samples gtest)
-endif()
-
-########################################################################
-#
-# Google Test's own tests.
-#
-# You can skip this section if you aren't interested in testing
-# Google Test itself.
-#
-# The tests are not built by default. To build them, set the
-# gtest_build_tests option to ON. You can do it by running ccmake
-# or specifying the -Dgtest_build_tests=ON flag when running cmake.
-
-if (gtest_build_tests)
- # This must be set in the root directory for the tests to be run by
- # 'make test' or ctest.
- enable_testing()
-
- if (WIN32)
- file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1"
- CONTENT
-"$project_bin = \"${CMAKE_BINARY_DIR}/bin/$<CONFIG>\"
-$env:Path = \"$project_bin;$env:Path\"
-& $args")
- elseif (MINGW OR CYGWIN)
- file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1"
- CONTENT
-"$project_bin = (cygpath --windows ${CMAKE_BINARY_DIR}/bin)
-$env:Path = \"$project_bin;$env:Path\"
-& $args")
- endif()
-
- ############################################################
- # C++ tests built with standard compiler flags.
-
- cxx_test(googletest-death-test-test gtest_main)
- cxx_test(gtest_environment_test gtest)
- cxx_test(googletest-filepath-test gtest_main)
- cxx_test(googletest-listener-test gtest_main)
- cxx_test(gtest_main_unittest gtest_main)
- cxx_test(googletest-message-test gtest_main)
- cxx_test(gtest_no_test_unittest gtest)
- cxx_test(googletest-options-test gtest_main)
- cxx_test(googletest-param-test-test gtest
- test/googletest-param-test2-test.cc)
- cxx_test(googletest-port-test gtest_main)
- cxx_test(gtest_pred_impl_unittest gtest_main)
- cxx_test(gtest_premature_exit_test gtest
- test/gtest_premature_exit_test.cc)
- cxx_test(googletest-printers-test gtest_main)
- cxx_test(gtest_prod_test gtest_main
- test/production.cc)
- cxx_test(gtest_repeat_test gtest)
- cxx_test(gtest_sole_header_test gtest_main)
- cxx_test(gtest_stress_test gtest)
- cxx_test(googletest-test-part-test gtest_main)
- cxx_test(gtest_throw_on_failure_ex_test gtest)
- cxx_test(gtest-typed-test_test gtest_main
- test/gtest-typed-test2_test.cc)
- cxx_test(gtest_unittest gtest_main)
- cxx_test(gtest-unittest-api_test gtest)
- cxx_test(gtest_skip_in_environment_setup_test gtest_main)
- cxx_test(gtest_skip_test gtest_main)
-
- ############################################################
- # C++ tests built with non-standard compiler flags.
-
- # MSVC 7.1 does not support STL with exceptions disabled.
- if (NOT MSVC OR MSVC_VERSION GREATER 1310)
- cxx_library(gtest_no_exception "${cxx_no_exception}"
- src/gtest-all.cc)
- cxx_library(gtest_main_no_exception "${cxx_no_exception}"
- src/gtest-all.cc src/gtest_main.cc)
- endif()
- cxx_library(gtest_main_no_rtti "${cxx_no_rtti}"
- src/gtest-all.cc src/gtest_main.cc)
-
- cxx_test_with_flags(gtest-death-test_ex_nocatch_test
- "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=0"
- gtest test/googletest-death-test_ex_test.cc)
- cxx_test_with_flags(gtest-death-test_ex_catch_test
- "${cxx_exception} -DGTEST_ENABLE_CATCH_EXCEPTIONS_=1"
- gtest test/googletest-death-test_ex_test.cc)
-
- cxx_test_with_flags(gtest_no_rtti_unittest "${cxx_no_rtti}"
- gtest_main_no_rtti test/gtest_unittest.cc)
-
- cxx_shared_library(gtest_dll "${cxx_default}"
- src/gtest-all.cc src/gtest_main.cc)
-
- cxx_executable_with_flags(gtest_dll_test_ "${cxx_default}"
- gtest_dll test/gtest_all_test.cc)
- set_target_properties(gtest_dll_test_
- PROPERTIES
- COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
-
- ############################################################
- # Python tests.
-
- cxx_executable(googletest-break-on-failure-unittest_ test gtest)
- py_test(googletest-break-on-failure-unittest)
-
- py_test(gtest_skip_environment_check_output_test)
-
- # Visual Studio .NET 2003 does not support STL with exceptions disabled.
- if (NOT MSVC OR MSVC_VERSION GREATER 1310) # 1310 is Visual Studio .NET 2003
- cxx_executable_with_flags(
- googletest-catch-exceptions-no-ex-test_
- "${cxx_no_exception}"
- gtest_main_no_exception
- test/googletest-catch-exceptions-test_.cc)
- endif()
-
- cxx_executable_with_flags(
- googletest-catch-exceptions-ex-test_
- "${cxx_exception}"
- gtest_main
- test/googletest-catch-exceptions-test_.cc)
- py_test(googletest-catch-exceptions-test)
-
- cxx_executable(googletest-color-test_ test gtest)
- py_test(googletest-color-test)
-
- cxx_executable(googletest-env-var-test_ test gtest)
- py_test(googletest-env-var-test)
-
- cxx_executable(googletest-filter-unittest_ test gtest)
- py_test(googletest-filter-unittest)
-
- cxx_executable(gtest_help_test_ test gtest_main)
- py_test(gtest_help_test)
-
- cxx_executable(googletest-list-tests-unittest_ test gtest)
- py_test(googletest-list-tests-unittest)
-
- cxx_executable(googletest-output-test_ test gtest)
- py_test(googletest-output-test --no_stacktrace_support)
-
- cxx_executable(googletest-shuffle-test_ test gtest)
- py_test(googletest-shuffle-test)
-
- # MSVC 7.1 does not support STL with exceptions disabled.
- if (NOT MSVC OR MSVC_VERSION GREATER 1310)
- cxx_executable(googletest-throw-on-failure-test_ test gtest_no_exception)
- set_target_properties(googletest-throw-on-failure-test_
- PROPERTIES
- COMPILE_FLAGS "${cxx_no_exception}")
- py_test(googletest-throw-on-failure-test)
- endif()
-
- cxx_executable(googletest-uninitialized-test_ test gtest)
- py_test(googletest-uninitialized-test)
-
- cxx_executable(gtest_xml_outfile1_test_ test gtest_main)
- cxx_executable(gtest_xml_outfile2_test_ test gtest_main)
- py_test(gtest_xml_outfiles_test)
- py_test(googletest-json-outfiles-test)
-
- cxx_executable(gtest_xml_output_unittest_ test gtest)
- py_test(gtest_xml_output_unittest --no_stacktrace_support)
- py_test(googletest-json-output-unittest --no_stacktrace_support)
-endif()
+++ /dev/null
-# This file contains a list of people who've made non-trivial
-# contribution to the Google C++ Testing Framework project. People
-# who commit code to the project are encouraged to add their names
-# here. Please keep the list sorted by first names.
-
-Ajay Joshi <jaj@google.com>
-Balázs Dán <balazs.dan@gmail.com>
-Bharat Mediratta <bharat@menalto.com>
-Chandler Carruth <chandlerc@google.com>
-Chris Prince <cprince@google.com>
-Chris Taylor <taylorc@google.com>
-Dan Egnor <egnor@google.com>
-Eric Roman <eroman@chromium.org>
-Hady Zalek <hady.zalek@gmail.com>
-Jeffrey Yasskin <jyasskin@google.com>
-Jói Sigurðsson <joi@google.com>
-Keir Mierle <mierle@gmail.com>
-Keith Ray <keith.ray@gmail.com>
-Kenton Varda <kenton@google.com>
-Manuel Klimek <klimek@google.com>
-Markus Heule <markus.heule@gmail.com>
-Mika Raento <mikie@iki.fi>
-Miklós Fazekas <mfazekas@szemafor.com>
-Pasi Valminen <pasi.valminen@gmail.com>
-Patrick Hanna <phanna@google.com>
-Patrick Riley <pfr@google.com>
-Peter Kaminski <piotrk@google.com>
-Preston Jackson <preston.a.jackson@gmail.com>
-Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
-Russ Cox <rsc@google.com>
-Russ Rufer <russ@pentad.com>
-Sean Mcafee <eefacm@gmail.com>
-Sigurður Ásgeirsson <siggi@google.com>
-Tracy Bialik <tracy@pentad.com>
-Vadim Berman <vadimb@google.com>
-Vlad Losev <vladl@google.com>
-Zhanyong Wan <wan@google.com>
+++ /dev/null
-Copyright 2008, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
- * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+++ /dev/null
-### Generic Build Instructions
-
-#### Setup
-
-To build Google Test and your tests that use it, you need to tell your build
-system where to find its headers and source files. The exact way to do it
-depends on which build system you use, and is usually straightforward.
-
-### Build with CMake
-
-Google Test comes with a CMake build script (
-[CMakeLists.txt](https://github.com/google/googletest/blob/master/CMakeLists.txt))
-that can be used on a wide range of platforms ("C" stands for cross-platform.).
-If you don't have CMake installed already, you can download it for free from
-<http://www.cmake.org/>.
-
-CMake works by generating native makefiles or build projects that can be used in
-the compiler environment of your choice. You can either build Google Test as a
-standalone project or it can be incorporated into an existing CMake build for
-another project.
-
-#### Standalone CMake Project
-
-When building Google Test as a standalone project, the typical workflow starts
-with:
-
- mkdir mybuild # Create a directory to hold the build output.
- cd mybuild
- cmake ${GTEST_DIR} # Generate native build scripts.
-
-If you want to build Google Test's samples, you should replace the last command
-with
-
- cmake -Dgtest_build_samples=ON ${GTEST_DIR}
-
-If you are on a \*nix system, you should now see a Makefile in the current
-directory. Just type 'make' to build gtest.
-
-If you use Windows and have Visual Studio installed, a `gtest.sln` file and
-several `.vcproj` files will be created. You can then build them using Visual
-Studio.
-
-On Mac OS X with Xcode installed, a `.xcodeproj` file will be generated.
-
-#### Incorporating Into An Existing CMake Project
-
-If you want to use gtest in a project which already uses CMake, then a more
-robust and flexible approach is to build gtest as part of that project directly.
-This is done by making the GoogleTest source code available to the main build
-and adding it using CMake's `add_subdirectory()` command. This has the
-significant advantage that the same compiler and linker settings are used
-between gtest and the rest of your project, so issues associated with using
-incompatible libraries (eg debug/release), etc. are avoided. This is
-particularly useful on Windows. Making GoogleTest's source code available to the
-main build can be done a few different ways:
-
-* Download the GoogleTest source code manually and place it at a known
- location. This is the least flexible approach and can make it more difficult
- to use with continuous integration systems, etc.
-* Embed the GoogleTest source code as a direct copy in the main project's
- source tree. This is often the simplest approach, but is also the hardest to
- keep up to date. Some organizations may not permit this method.
-* Add GoogleTest as a git submodule or equivalent. This may not always be
- possible or appropriate. Git submodules, for example, have their own set of
- advantages and drawbacks.
-* Use CMake to download GoogleTest as part of the build's configure step. This
- is just a little more complex, but doesn't have the limitations of the other
- methods.
-
-The last of the above methods is implemented with a small piece of CMake code in
-a separate file (e.g. `CMakeLists.txt.in`) which is copied to the build area and
-then invoked as a sub-build _during the CMake stage_. That directory is then
-pulled into the main build with `add_subdirectory()`. For example:
-
-New file `CMakeLists.txt.in`:
-
-```cmake
-cmake_minimum_required(VERSION 2.8.2)
-
-project(googletest-download NONE)
-
-include(ExternalProject)
-ExternalProject_Add(googletest
- GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG master
- SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
- BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- TEST_COMMAND ""
-)
-```
-
-Existing build's `CMakeLists.txt`:
-
-```cmake
-# Download and unpack googletest at configure time
-configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
-execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
- RESULT_VARIABLE result
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
-if(result)
- message(FATAL_ERROR "CMake step for googletest failed: ${result}")
-endif()
-execute_process(COMMAND ${CMAKE_COMMAND} --build .
- RESULT_VARIABLE result
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
-if(result)
- message(FATAL_ERROR "Build step for googletest failed: ${result}")
-endif()
-
-# Prevent overriding the parent project's compiler/linker
-# settings on Windows
-set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
-
-# Add googletest directly to our build. This defines
-# the gtest and gtest_main targets.
-add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
- ${CMAKE_CURRENT_BINARY_DIR}/googletest-build
- EXCLUDE_FROM_ALL)
-
-# The gtest/gtest_main targets carry header search path
-# dependencies automatically when using CMake 2.8.11 or
-# later. Otherwise we have to add them here ourselves.
-if (CMAKE_VERSION VERSION_LESS 2.8.11)
- include_directories("${gtest_SOURCE_DIR}/include")
-endif()
-
-# Now simply link against gtest or gtest_main as needed. Eg
-add_executable(example example.cpp)
-target_link_libraries(example gtest_main)
-add_test(NAME example_test COMMAND example)
-```
-
-Note that this approach requires CMake 2.8.2 or later due to its use of the
-`ExternalProject_Add()` command. The above technique is discussed in more detail
-in [this separate article](http://crascit.com/2015/07/25/cmake-gtest/) which
-also contains a link to a fully generalized implementation of the technique.
-
-##### Visual Studio Dynamic vs Static Runtimes
-
-By default, new Visual Studio projects link the C runtimes dynamically but
-Google Test links them statically. This will generate an error that looks
-something like the following: gtest.lib(gtest-all.obj) : error LNK2038: mismatch
-detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value
-'MDd_DynamicDebug' in main.obj
-
-Google Test already has a CMake option for this: `gtest_force_shared_crt`
-
-Enabling this option will make gtest link the runtimes dynamically too, and
-match the project in which it is included.
-
-#### C++ Standard Version
-
-An environment that supports C++11 is required in order to successfully build
-Google Test. One way to ensure this is to specify the standard in the top-level
-project, for example by using the `set(CMAKE_CXX_STANDARD 11)` command. If this
-is not feasible, for example in a C project using Google Test for validation,
-then it can be specified by adding it to the options for cmake via the
-`DCMAKE_CXX_FLAGS` option.
-
-### Tweaking Google Test
-
-Google Test can be used in diverse environments. The default configuration may
-not work (or may not work well) out of the box in some environments. However,
-you can easily tweak Google Test by defining control macros on the compiler
-command line. Generally, these macros are named like `GTEST_XYZ` and you define
-them to either 1 or 0 to enable or disable a certain feature.
-
-We list the most frequently used macros below. For a complete list, see file
-[include/gtest/internal/gtest-port.h](https://github.com/google/googletest/blob/master/googletest/include/gtest/internal/gtest-port.h).
-
-### Multi-threaded Tests
-
-Google Test is thread-safe where the pthread library is available. After
-`#include "gtest/gtest.h"`, you can check the
-`GTEST_IS_THREADSAFE` macro to see whether this is the case (yes if the macro is
-`#defined` to 1, no if it's undefined.).
-
-If Google Test doesn't correctly detect whether pthread is available in your
-environment, you can force it with
-
- -DGTEST_HAS_PTHREAD=1
-
-or
-
- -DGTEST_HAS_PTHREAD=0
-
-When Google Test uses pthread, you may need to add flags to your compiler and/or
-linker to select the pthread library, or you'll get link errors. If you use the
-CMake script or the deprecated Autotools script, this is taken care of for you.
-If you use your own build script, you'll need to read your compiler and linker's
-manual to figure out what flags to add.
-
-### As a Shared Library (DLL)
-
-Google Test is compact, so most users can build and link it as a static library
-for the simplicity. You can choose to use Google Test as a shared library (known
-as a DLL on Windows) if you prefer.
-
-To compile *gtest* as a shared library, add
-
- -DGTEST_CREATE_SHARED_LIBRARY=1
-
-to the compiler flags. You'll also need to tell the linker to produce a shared
-library instead - consult your linker's manual for how to do it.
-
-To compile your *tests* that use the gtest shared library, add
-
- -DGTEST_LINKED_AS_SHARED_LIBRARY=1
-
-to the compiler flags.
-
-Note: while the above steps aren't technically necessary today when using some
-compilers (e.g. GCC), they may become necessary in the future, if we decide to
-improve the speed of loading the library (see
-<http://gcc.gnu.org/wiki/Visibility> for details). Therefore you are recommended
-to always add the above flags when using Google Test as a shared library.
-Otherwise a future release of Google Test may break your build script.
-
-### Avoiding Macro Name Clashes
-
-In C++, macros don't obey namespaces. Therefore two libraries that both define a
-macro of the same name will clash if you `#include` both definitions. In case a
-Google Test macro clashes with another library, you can force Google Test to
-rename its macro to avoid the conflict.
-
-Specifically, if both Google Test and some other code define macro FOO, you can
-add
-
- -DGTEST_DONT_DEFINE_FOO=1
-
-to the compiler flags to tell Google Test to change the macro's name from `FOO`
-to `GTEST_FOO`. Currently `FOO` can be `FAIL`, `SUCCEED`, or `TEST`. For
-example, with `-DGTEST_DONT_DEFINE_TEST=1`, you'll need to write
-
- GTEST_TEST(SomeTest, DoesThis) { ... }
-
-instead of
-
- TEST(SomeTest, DoesThis) { ... }
-
-in order to define a test.
+++ /dev/null
-@PACKAGE_INIT@
-include(CMakeFindDependencyMacro)
-if (@GTEST_HAS_PTHREAD@)
- set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@)
- find_dependency(Threads)
-endif()
-
-include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
-check_required_components("@project_name@")
+++ /dev/null
-prefix=${pcfiledir}/../..
-libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
-includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
-
-Name: gtest
-Description: GoogleTest (without main() function)
-Version: @PROJECT_VERSION@
-URL: https://github.com/google/googletest
-Libs: -L${libdir} -lgtest @CMAKE_THREAD_LIBS_INIT@
-Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
+++ /dev/null
-prefix=${pcfiledir}/../..
-libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
-includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
-
-Name: gtest_main
-Description: GoogleTest (with main() function)
-Version: @PROJECT_VERSION@
-URL: https://github.com/google/googletest
-Requires: gtest
-Libs: -L${libdir} -lgtest_main @CMAKE_THREAD_LIBS_INIT@
-Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@
+++ /dev/null
-# Defines functions and macros useful for building Google Test and
-# Google Mock.
-#
-# Note:
-#
-# - This file will be run twice when building Google Mock (once via
-# Google Test's CMakeLists.txt, and once via Google Mock's).
-# Therefore it shouldn't have any side effects other than defining
-# the functions and macros.
-#
-# - The functions/macros defined in this file may depend on Google
-# Test and Google Mock's option() definitions, and thus must be
-# called *after* the options have been defined.
-
-if (POLICY CMP0054)
- cmake_policy(SET CMP0054 NEW)
-endif (POLICY CMP0054)
-
-# Tweaks CMake's default compiler/linker settings to suit Google Test's needs.
-#
-# This must be a macro(), as inside a function string() can only
-# update variables in the function scope.
-macro(fix_default_compiler_settings_)
- if (MSVC)
- # For MSVC, CMake sets certain flags to defaults we want to override.
- # This replacement code is taken from sample in the CMake Wiki at
- # https://gitlab.kitware.com/cmake/community/wikis/FAQ#dynamic-replace.
- foreach (flag_var
- CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
- CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
- CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
- CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
- if (NOT BUILD_SHARED_LIBS AND NOT gtest_force_shared_crt)
- # When Google Test is built as a shared library, it should also use
- # shared runtime libraries. Otherwise, it may end up with multiple
- # copies of runtime library data in different modules, resulting in
- # hard-to-find crashes. When it is built as a static library, it is
- # preferable to use CRT as static libraries, as we don't have to rely
- # on CRT DLLs being available. CMake always defaults to using shared
- # CRT libraries, so we override that default here.
- string(REPLACE "/MD" "-MT" ${flag_var} "${${flag_var}}")
- endif()
-
- # We prefer more strict warning checking for building Google Test.
- # Replaces /W3 with /W4 in defaults.
- string(REPLACE "/W3" "/W4" ${flag_var} "${${flag_var}}")
-
- # Prevent D9025 warning for targets that have exception handling
- # turned off (/EHs-c- flag). Where required, exceptions are explicitly
- # re-enabled using the cxx_exception_flags variable.
- string(REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}")
- endforeach()
- endif()
-endmacro()
-
-# Defines the compiler/linker flags used to build Google Test and
-# Google Mock. You can tweak these definitions to suit your need. A
-# variable's value is empty before it's explicitly assigned to.
-macro(config_compiler_and_linker)
- # Note: pthreads on MinGW is not supported, even if available
- # instead, we use windows threading primitives
- unset(GTEST_HAS_PTHREAD)
- if (NOT gtest_disable_pthreads AND NOT MINGW)
- # Defines CMAKE_USE_PTHREADS_INIT and CMAKE_THREAD_LIBS_INIT.
- find_package(Threads)
- if (CMAKE_USE_PTHREADS_INIT)
- set(GTEST_HAS_PTHREAD ON)
- endif()
- endif()
-
- fix_default_compiler_settings_()
- if (MSVC)
- # Newlines inside flags variables break CMake's NMake generator.
- # TODO(vladl@google.com): Add -RTCs and -RTCu to debug builds.
- set(cxx_base_flags "-GS -W4 -WX -wd4251 -wd4275 -nologo -J -Zi")
- set(cxx_base_flags "${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32")
- set(cxx_base_flags "${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN")
- set(cxx_exception_flags "-EHsc -D_HAS_EXCEPTIONS=1")
- set(cxx_no_exception_flags "-EHs-c- -D_HAS_EXCEPTIONS=0")
- set(cxx_no_rtti_flags "-GR-")
- # Suppress "unreachable code" warning
- # http://stackoverflow.com/questions/3232669 explains the issue.
- set(cxx_base_flags "${cxx_base_flags} -wd4702")
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
- set(cxx_base_flags "-Wall -Wshadow -Werror -Wconversion")
- set(cxx_exception_flags "-fexceptions")
- set(cxx_no_exception_flags "-fno-exceptions")
- set(cxx_strict_flags "-W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls")
- set(cxx_no_rtti_flags "-fno-rtti")
- elseif (CMAKE_COMPILER_IS_GNUCXX)
- set(cxx_base_flags "-Wall -Wshadow -Werror")
- if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0)
- set(cxx_base_flags "${cxx_base_flags} -Wno-error=dangling-else")
- endif()
- set(cxx_exception_flags "-fexceptions")
- set(cxx_no_exception_flags "-fno-exceptions")
- # Until version 4.3.2, GCC doesn't define a macro to indicate
- # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
- # explicitly.
- set(cxx_no_rtti_flags "-fno-rtti -DGTEST_HAS_RTTI=0")
- set(cxx_strict_flags
- "-Wextra -Wno-unused-parameter -Wno-missing-field-initializers")
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "SunPro")
- set(cxx_exception_flags "-features=except")
- # Sun Pro doesn't provide macros to indicate whether exceptions and
- # RTTI are enabled, so we define GTEST_HAS_* explicitly.
- set(cxx_no_exception_flags "-features=no%except -DGTEST_HAS_EXCEPTIONS=0")
- set(cxx_no_rtti_flags "-features=no%rtti -DGTEST_HAS_RTTI=0")
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "VisualAge" OR
- CMAKE_CXX_COMPILER_ID STREQUAL "XL")
- # CMake 2.8 changes Visual Age's compiler ID to "XL".
- set(cxx_exception_flags "-qeh")
- set(cxx_no_exception_flags "-qnoeh")
- # Until version 9.0, Visual Age doesn't define a macro to indicate
- # whether RTTI is enabled. Therefore we define GTEST_HAS_RTTI
- # explicitly.
- set(cxx_no_rtti_flags "-qnortti -DGTEST_HAS_RTTI=0")
- elseif (CMAKE_CXX_COMPILER_ID STREQUAL "HP")
- set(cxx_base_flags "-AA -mt")
- set(cxx_exception_flags "-DGTEST_HAS_EXCEPTIONS=1")
- set(cxx_no_exception_flags "+noeh -DGTEST_HAS_EXCEPTIONS=0")
- # RTTI can not be disabled in HP aCC compiler.
- set(cxx_no_rtti_flags "")
- endif()
-
- # The pthreads library is available and allowed?
- if (DEFINED GTEST_HAS_PTHREAD)
- set(GTEST_HAS_PTHREAD_MACRO "-DGTEST_HAS_PTHREAD=1")
- else()
- set(GTEST_HAS_PTHREAD_MACRO "-DGTEST_HAS_PTHREAD=0")
- endif()
- set(cxx_base_flags "${cxx_base_flags} ${GTEST_HAS_PTHREAD_MACRO}")
-
- # For building gtest's own tests and samples.
- set(cxx_exception "${cxx_base_flags} ${cxx_exception_flags}")
- set(cxx_no_exception
- "${CMAKE_CXX_FLAGS} ${cxx_base_flags} ${cxx_no_exception_flags}")
- set(cxx_default "${cxx_exception}")
- set(cxx_no_rtti "${cxx_default} ${cxx_no_rtti_flags}")
-
- # For building the gtest libraries.
- set(cxx_strict "${cxx_default} ${cxx_strict_flags}")
-endmacro()
-
-# Defines the gtest & gtest_main libraries. User tests should link
-# with one of them.
-function(cxx_library_with_type name type cxx_flags)
- # type can be either STATIC or SHARED to denote a static or shared library.
- # ARGN refers to additional arguments after 'cxx_flags'.
- add_library(${name} ${type} ${ARGN})
- set_target_properties(${name}
- PROPERTIES
- COMPILE_FLAGS "${cxx_flags}")
- # Generate debug library name with a postfix.
- set_target_properties(${name}
- PROPERTIES
- DEBUG_POSTFIX "d")
- # Set the output directory for build artifacts
- set_target_properties(${name}
- PROPERTIES
- RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
- LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
- ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
- PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
- # make PDBs match library name
- get_target_property(pdb_debug_postfix ${name} DEBUG_POSTFIX)
- set_target_properties(${name}
- PROPERTIES
- PDB_NAME "${name}"
- PDB_NAME_DEBUG "${name}${pdb_debug_postfix}"
- COMPILE_PDB_NAME "${name}"
- COMPILE_PDB_NAME_DEBUG "${name}${pdb_debug_postfix}")
-
- if (BUILD_SHARED_LIBS OR type STREQUAL "SHARED")
- set_target_properties(${name}
- PROPERTIES
- COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
- if (NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11")
- target_compile_definitions(${name} INTERFACE
- $<INSTALL_INTERFACE:GTEST_LINKED_AS_SHARED_LIBRARY=1>)
- endif()
- endif()
- if (DEFINED GTEST_HAS_PTHREAD)
- if ("${CMAKE_VERSION}" VERSION_LESS "3.1.0")
- set(threads_spec ${CMAKE_THREAD_LIBS_INIT})
- else()
- set(threads_spec Threads::Threads)
- endif()
- target_link_libraries(${name} PUBLIC ${threads_spec})
- endif()
-endfunction()
-
-########################################################################
-#
-# Helper functions for creating build targets.
-
-function(cxx_shared_library name cxx_flags)
- cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN})
-endfunction()
-
-function(cxx_library name cxx_flags)
- cxx_library_with_type(${name} "" "${cxx_flags}" ${ARGN})
-endfunction()
-
-# cxx_executable_with_flags(name cxx_flags libs srcs...)
-#
-# creates a named C++ executable that depends on the given libraries and
-# is built from the given source files with the given compiler flags.
-function(cxx_executable_with_flags name cxx_flags libs)
- add_executable(${name} ${ARGN})
- if (MSVC)
- # BigObj required for tests.
- set(cxx_flags "${cxx_flags} -bigobj")
- endif()
- if (cxx_flags)
- set_target_properties(${name}
- PROPERTIES
- COMPILE_FLAGS "${cxx_flags}")
- endif()
- if (BUILD_SHARED_LIBS)
- set_target_properties(${name}
- PROPERTIES
- COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1")
- endif()
- # To support mixing linking in static and dynamic libraries, link each
- # library in with an extra call to target_link_libraries.
- foreach (lib "${libs}")
- target_link_libraries(${name} ${lib})
- endforeach()
-endfunction()
-
-# cxx_executable(name dir lib srcs...)
-#
-# creates a named target that depends on the given libs and is built
-# from the given source files. dir/name.cc is implicitly included in
-# the source file list.
-function(cxx_executable name dir libs)
- cxx_executable_with_flags(
- ${name} "${cxx_default}" "${libs}" "${dir}/${name}.cc" ${ARGN})
-endfunction()
-
-# Sets PYTHONINTERP_FOUND and PYTHON_EXECUTABLE.
-find_package(PythonInterp)
-
-# cxx_test_with_flags(name cxx_flags libs srcs...)
-#
-# creates a named C++ test that depends on the given libs and is built
-# from the given source files with the given compiler flags.
-function(cxx_test_with_flags name cxx_flags libs)
- cxx_executable_with_flags(${name} "${cxx_flags}" "${libs}" ${ARGN})
- if (WIN32 OR MINGW)
- add_test(NAME ${name}
- COMMAND "powershell" "-Command" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1" "$<TARGET_FILE:${name}>")
- else()
- add_test(NAME ${name}
- COMMAND "$<TARGET_FILE:${name}>")
- endif()
-endfunction()
-
-# cxx_test(name libs srcs...)
-#
-# creates a named test target that depends on the given libs and is
-# built from the given source files. Unlike cxx_test_with_flags,
-# test/name.cc is already implicitly included in the source file list.
-function(cxx_test name libs)
- cxx_test_with_flags("${name}" "${cxx_default}" "${libs}"
- "test/${name}.cc" ${ARGN})
-endfunction()
-
-# py_test(name)
-#
-# creates a Python test with the given name whose main module is in
-# test/name.py. It does nothing if Python is not installed.
-function(py_test name)
- if (PYTHONINTERP_FOUND)
- if ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 3.1)
- if (CMAKE_CONFIGURATION_TYPES)
- # Multi-configuration build generators as for Visual Studio save
- # output in a subdirectory of CMAKE_CURRENT_BINARY_DIR (Debug,
- # Release etc.), so we have to provide it here.
- if (WIN32 OR MINGW)
- add_test(NAME ${name}
- COMMAND powershell -Command ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/RunTest.ps1
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
- --build_dir=${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG> ${ARGN})
- else()
- add_test(NAME ${name}
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
- --build_dir=${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG> ${ARGN})
- endif()
- else (CMAKE_CONFIGURATION_TYPES)
- # Single-configuration build generators like Makefile generators
- # don't have subdirs below CMAKE_CURRENT_BINARY_DIR.
- if (WIN32 OR MINGW)
- add_test(NAME ${name}
- COMMAND powershell -Command ${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
- --build_dir=${CMAKE_CURRENT_BINARY_DIR} ${ARGN})
- else()
- add_test(NAME ${name}
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
- --build_dir=${CMAKE_CURRENT_BINARY_DIR} ${ARGN})
- endif()
- endif (CMAKE_CONFIGURATION_TYPES)
- else()
- # ${CMAKE_CURRENT_BINARY_DIR} is known at configuration time, so we can
- # directly bind it from cmake. ${CTEST_CONFIGURATION_TYPE} is known
- # only at ctest runtime (by calling ctest -c <Configuration>), so
- # we have to escape $ to delay variable substitution here.
- if (WIN32 OR MINGW)
- add_test(NAME ${name}
- COMMAND powershell -Command ${CMAKE_CURRENT_BINARY_DIR}/RunTest.ps1
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
- --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
- else()
- add_test(NAME ${name}
- COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/${name}.py
- --build_dir=${CMAKE_CURRENT_BINARY_DIR}/\${CTEST_CONFIGURATION_TYPE} ${ARGN})
- endif()
- endif()
- endif(PYTHONINTERP_FOUND)
-endfunction()
-
-# install_project(targets...)
-#
-# Installs the specified targets and configures the associated pkgconfig files.
-function(install_project)
- if(INSTALL_GTEST)
- install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/"
- DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
- # Install the project targets.
- install(TARGETS ${ARGN}
- EXPORT ${targets_export_name}
- RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
- ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
- if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
- # Install PDBs
- foreach(t ${ARGN})
- get_target_property(t_pdb_name ${t} COMPILE_PDB_NAME)
- get_target_property(t_pdb_name_debug ${t} COMPILE_PDB_NAME_DEBUG)
- get_target_property(t_pdb_output_directory ${t} PDB_OUTPUT_DIRECTORY)
- install(FILES
- "${t_pdb_output_directory}/\${CMAKE_INSTALL_CONFIG_NAME}/$<$<CONFIG:Debug>:${t_pdb_name_debug}>$<$<NOT:$<CONFIG:Debug>>:${t_pdb_name}>.pdb"
- DESTINATION ${CMAKE_INSTALL_LIBDIR}
- OPTIONAL)
- endforeach()
- endif()
- # Configure and install pkgconfig files.
- foreach(t ${ARGN})
- set(configured_pc "${generated_dir}/${t}.pc")
- configure_file("${PROJECT_SOURCE_DIR}/cmake/${t}.pc.in"
- "${configured_pc}" @ONLY)
- install(FILES "${configured_pc}"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
- endforeach()
- endif()
-endfunction()
+++ /dev/null
-# libgtest.la - a libtool library file
-# Generated by libtool (GNU libtool) 2.4.6
-
-# Please DO NOT delete this file!
-# It is necessary for linking the library.
-
-# Names of this library.
-library_names='libgtest.so'
-
-# Is this an already installed library?
-installed=yes
-
-# Should we warn about portability when linking against -modules?
-shouldnotlink=no
-
-# Files to dlopen/dlpreopen
-dlopen=''
-dlpreopen=''
-
-# Directory that this library needs to be installed in:
-libdir='@CMAKE_INSTALL_FULL_LIBDIR@'
+++ /dev/null
-# Advanced googletest Topics
-
-<!-- GOOGLETEST_CM0016 DO NOT DELETE -->
-
-## Introduction
-
-Now that you have read the [googletest Primer](primer.md) and learned how to
-write tests using googletest, it's time to learn some new tricks. This document
-will show you more assertions as well as how to construct complex failure
-messages, propagate fatal failures, reuse and speed up your test fixtures, and
-use various flags with your tests.
-
-## More Assertions
-
-This section covers some less frequently used, but still significant,
-assertions.
-
-### Explicit Success and Failure
-
-These three assertions do not actually test a value or expression. Instead, they
-generate a success or failure directly. Like the macros that actually perform a
-test, you may stream a custom failure message into them.
-
-```c++
-SUCCEED();
-```
-
-Generates a success. This does **NOT** make the overall test succeed. A test is
-considered successful only if none of its assertions fail during its execution.
-
-NOTE: `SUCCEED()` is purely documentary and currently doesn't generate any
-user-visible output. However, we may add `SUCCEED()` messages to googletest's
-output in the future.
-
-```c++
-FAIL();
-ADD_FAILURE();
-ADD_FAILURE_AT("file_path", line_number);
-```
-
-`FAIL()` generates a fatal failure, while `ADD_FAILURE()` and `ADD_FAILURE_AT()`
-generate a nonfatal failure. These are useful when control flow, rather than a
-Boolean expression, determines the test's success or failure. For example, you
-might want to write something like:
-
-```c++
-switch(expression) {
- case 1:
- ... some checks ...
- case 2:
- ... some other checks ...
- default:
- FAIL() << "We shouldn't get here.";
-}
-```
-
-NOTE: you can only use `FAIL()` in functions that return `void`. See the
-[Assertion Placement section](#assertion-placement) for more information.
-
-### Exception Assertions
-
-These are for verifying that a piece of code throws (or does not throw) an
-exception of the given type:
-
-Fatal assertion | Nonfatal assertion | Verifies
------------------------------------------- | ------------------------------------------ | --------
-`ASSERT_THROW(statement, exception_type);` | `EXPECT_THROW(statement, exception_type);` | `statement` throws an exception of the given type
-`ASSERT_ANY_THROW(statement);` | `EXPECT_ANY_THROW(statement);` | `statement` throws an exception of any type
-`ASSERT_NO_THROW(statement);` | `EXPECT_NO_THROW(statement);` | `statement` doesn't throw any exception
-
-Examples:
-
-```c++
-ASSERT_THROW(Foo(5), bar_exception);
-
-EXPECT_NO_THROW({
- int n = 5;
- Bar(&n);
-});
-```
-
-**Availability**: requires exceptions to be enabled in the build environment
-
-### Predicate Assertions for Better Error Messages
-
-Even though googletest has a rich set of assertions, they can never be complete,
-as it's impossible (nor a good idea) to anticipate all scenarios a user might
-run into. Therefore, sometimes a user has to use `EXPECT_TRUE()` to check a
-complex expression, for lack of a better macro. This has the problem of not
-showing you the values of the parts of the expression, making it hard to
-understand what went wrong. As a workaround, some users choose to construct the
-failure message by themselves, streaming it into `EXPECT_TRUE()`. However, this
-is awkward especially when the expression has side-effects or is expensive to
-evaluate.
-
-googletest gives you three different options to solve this problem:
-
-#### Using an Existing Boolean Function
-
-If you already have a function or functor that returns `bool` (or a type that
-can be implicitly converted to `bool`), you can use it in a *predicate
-assertion* to get the function arguments printed for free:
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-| Fatal assertion | Nonfatal assertion | Verifies |
-| --------------------------------- | --------------------------------- | --------------------------- |
-| `ASSERT_PRED1(pred1, val1)` | `EXPECT_PRED1(pred1, val1)` | `pred1(val1)` is true |
-| `ASSERT_PRED2(pred2, val1, val2)` | `EXPECT_PRED2(pred2, val1, val2)` | `pred1(val1, val2)` is true |
-| `...` | `...` | `...` |
-
-<!-- mdformat on-->
-In the above, `predn` is an `n`-ary predicate function or functor, where `val1`,
-`val2`, ..., and `valn` are its arguments. The assertion succeeds if the
-predicate returns `true` when applied to the given arguments, and fails
-otherwise. When the assertion fails, it prints the value of each argument. In
-either case, the arguments are evaluated exactly once.
-
-Here's an example. Given
-
-```c++
-// Returns true if m and n have no common divisors except 1.
-bool MutuallyPrime(int m, int n) { ... }
-
-const int a = 3;
-const int b = 4;
-const int c = 10;
-```
-
-the assertion
-
-```c++
- EXPECT_PRED2(MutuallyPrime, a, b);
-```
-
-will succeed, while the assertion
-
-```c++
- EXPECT_PRED2(MutuallyPrime, b, c);
-```
-
-will fail with the message
-
-```none
-MutuallyPrime(b, c) is false, where
-b is 4
-c is 10
-```
-
-> NOTE:
->
-> 1. If you see a compiler error "no matching function to call" when using
-> `ASSERT_PRED*` or `EXPECT_PRED*`, please see
-> [this](faq.md#the-compiler-complains-no-matching-function-to-call-when-i-use-assert-pred-how-do-i-fix-it)
-> for how to resolve it.
-
-#### Using a Function That Returns an AssertionResult
-
-While `EXPECT_PRED*()` and friends are handy for a quick job, the syntax is not
-satisfactory: you have to use different macros for different arities, and it
-feels more like Lisp than C++. The `::testing::AssertionResult` class solves
-this problem.
-
-An `AssertionResult` object represents the result of an assertion (whether it's
-a success or a failure, and an associated message). You can create an
-`AssertionResult` using one of these factory functions:
-
-```c++
-namespace testing {
-
-// Returns an AssertionResult object to indicate that an assertion has
-// succeeded.
-AssertionResult AssertionSuccess();
-
-// Returns an AssertionResult object to indicate that an assertion has
-// failed.
-AssertionResult AssertionFailure();
-
-}
-```
-
-You can then use the `<<` operator to stream messages to the `AssertionResult`
-object.
-
-To provide more readable messages in Boolean assertions (e.g. `EXPECT_TRUE()`),
-write a predicate function that returns `AssertionResult` instead of `bool`. For
-example, if you define `IsEven()` as:
-
-```c++
-::testing::AssertionResult IsEven(int n) {
- if ((n % 2) == 0)
- return ::testing::AssertionSuccess();
- else
- return ::testing::AssertionFailure() << n << " is odd";
-}
-```
-
-instead of:
-
-```c++
-bool IsEven(int n) {
- return (n % 2) == 0;
-}
-```
-
-the failed assertion `EXPECT_TRUE(IsEven(Fib(4)))` will print:
-
-```none
-Value of: IsEven(Fib(4))
- Actual: false (3 is odd)
-Expected: true
-```
-
-instead of a more opaque
-
-```none
-Value of: IsEven(Fib(4))
- Actual: false
-Expected: true
-```
-
-If you want informative messages in `EXPECT_FALSE` and `ASSERT_FALSE` as well
-(one third of Boolean assertions in the Google code base are negative ones), and
-are fine with making the predicate slower in the success case, you can supply a
-success message:
-
-```c++
-::testing::AssertionResult IsEven(int n) {
- if ((n % 2) == 0)
- return ::testing::AssertionSuccess() << n << " is even";
- else
- return ::testing::AssertionFailure() << n << " is odd";
-}
-```
-
-Then the statement `EXPECT_FALSE(IsEven(Fib(6)))` will print
-
-```none
- Value of: IsEven(Fib(6))
- Actual: true (8 is even)
- Expected: false
-```
-
-#### Using a Predicate-Formatter
-
-If you find the default message generated by `(ASSERT|EXPECT)_PRED*` and
-`(ASSERT|EXPECT)_(TRUE|FALSE)` unsatisfactory, or some arguments to your
-predicate do not support streaming to `ostream`, you can instead use the
-following *predicate-formatter assertions* to *fully* customize how the message
-is formatted:
-
-Fatal assertion | Nonfatal assertion | Verifies
------------------------------------------------- | ------------------------------------------------ | --------
-`ASSERT_PRED_FORMAT1(pred_format1, val1);` | `EXPECT_PRED_FORMAT1(pred_format1, val1);` | `pred_format1(val1)` is successful
-`ASSERT_PRED_FORMAT2(pred_format2, val1, val2);` | `EXPECT_PRED_FORMAT2(pred_format2, val1, val2);` | `pred_format2(val1, val2)` is successful
-`...` | `...` | ...
-
-The difference between this and the previous group of macros is that instead of
-a predicate, `(ASSERT|EXPECT)_PRED_FORMAT*` take a *predicate-formatter*
-(`pred_formatn`), which is a function or functor with the signature:
-
-```c++
-::testing::AssertionResult PredicateFormattern(const char* expr1,
- const char* expr2,
- ...
- const char* exprn,
- T1 val1,
- T2 val2,
- ...
- Tn valn);
-```
-
-where `val1`, `val2`, ..., and `valn` are the values of the predicate arguments,
-and `expr1`, `expr2`, ..., and `exprn` are the corresponding expressions as they
-appear in the source code. The types `T1`, `T2`, ..., and `Tn` can be either
-value types or reference types. For example, if an argument has type `Foo`, you
-can declare it as either `Foo` or `const Foo&`, whichever is appropriate.
-
-As an example, let's improve the failure message in `MutuallyPrime()`, which was
-used with `EXPECT_PRED2()`:
-
-```c++
-// Returns the smallest prime common divisor of m and n,
-// or 1 when m and n are mutually prime.
-int SmallestPrimeCommonDivisor(int m, int n) { ... }
-
-// A predicate-formatter for asserting that two integers are mutually prime.
-::testing::AssertionResult AssertMutuallyPrime(const char* m_expr,
- const char* n_expr,
- int m,
- int n) {
- if (MutuallyPrime(m, n)) return ::testing::AssertionSuccess();
-
- return ::testing::AssertionFailure() << m_expr << " and " << n_expr
- << " (" << m << " and " << n << ") are not mutually prime, "
- << "as they have a common divisor " << SmallestPrimeCommonDivisor(m, n);
-}
-```
-
-With this predicate-formatter, we can use
-
-```c++
- EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c);
-```
-
-to generate the message
-
-```none
-b and c (4 and 10) are not mutually prime, as they have a common divisor 2.
-```
-
-As you may have realized, many of the built-in assertions we introduced earlier
-are special cases of `(EXPECT|ASSERT)_PRED_FORMAT*`. In fact, most of them are
-indeed defined using `(EXPECT|ASSERT)_PRED_FORMAT*`.
-
-### Floating-Point Comparison
-
-Comparing floating-point numbers is tricky. Due to round-off errors, it is very
-unlikely that two floating-points will match exactly. Therefore, `ASSERT_EQ` 's
-naive comparison usually doesn't work. And since floating-points can have a wide
-value range, no single fixed error bound works. It's better to compare by a
-fixed relative error bound, except for values close to 0 due to the loss of
-precision there.
-
-In general, for floating-point comparison to make sense, the user needs to
-carefully choose the error bound. If they don't want or care to, comparing in
-terms of Units in the Last Place (ULPs) is a good default, and googletest
-provides assertions to do this. Full details about ULPs are quite long; if you
-want to learn more, see
-[here](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
-
-#### Floating-Point Macros
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-| Fatal assertion | Nonfatal assertion | Verifies |
-| ------------------------------- | ------------------------------- | ---------------------------------------- |
-| `ASSERT_FLOAT_EQ(val1, val2);` | `EXPECT_FLOAT_EQ(val1, val2);` | the two `float` values are almost equal |
-| `ASSERT_DOUBLE_EQ(val1, val2);` | `EXPECT_DOUBLE_EQ(val1, val2);` | the two `double` values are almost equal |
-
-<!-- mdformat on-->
-
-By "almost equal" we mean the values are within 4 ULP's from each other.
-
-The following assertions allow you to choose the acceptable error bound:
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-| Fatal assertion | Nonfatal assertion | Verifies |
-| ------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------- |
-| `ASSERT_NEAR(val1, val2, abs_error);` | `EXPECT_NEAR(val1, val2, abs_error);` | the difference between `val1` and `val2` doesn't exceed the given absolute error |
-
-<!-- mdformat on-->
-
-#### Floating-Point Predicate-Format Functions
-
-Some floating-point operations are useful, but not that often used. In order to
-avoid an explosion of new macros, we provide them as predicate-format functions
-that can be used in predicate assertion macros (e.g. `EXPECT_PRED_FORMAT2`,
-etc).
-
-```c++
-EXPECT_PRED_FORMAT2(::testing::FloatLE, val1, val2);
-EXPECT_PRED_FORMAT2(::testing::DoubleLE, val1, val2);
-```
-
-Verifies that `val1` is less than, or almost equal to, `val2`. You can replace
-`EXPECT_PRED_FORMAT2` in the above table with `ASSERT_PRED_FORMAT2`.
-
-### Asserting Using gMock Matchers
-
-[gMock](../../googlemock) comes with a library of matchers for validating
-arguments passed to mock objects. A gMock *matcher* is basically a predicate
-that knows how to describe itself. It can be used in these assertion macros:
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-| Fatal assertion | Nonfatal assertion | Verifies |
-| ------------------------------ | ------------------------------ | --------------------- |
-| `ASSERT_THAT(value, matcher);` | `EXPECT_THAT(value, matcher);` | value matches matcher |
-
-<!-- mdformat on-->
-
-For example, `StartsWith(prefix)` is a matcher that matches a string starting
-with `prefix`, and you can write:
-
-```c++
-using ::testing::StartsWith;
-...
- // Verifies that Foo() returns a string starting with "Hello".
- EXPECT_THAT(Foo(), StartsWith("Hello"));
-```
-
-Read this
-[recipe](../../googlemock/docs/cook_book.md#using-matchers-in-googletest-assertions)
-in the gMock Cookbook for more details.
-
-gMock has a rich set of matchers. You can do many things googletest cannot do
-alone with them. For a list of matchers gMock provides, read
-[this](../../googlemock/docs/cook_book.md##using-matchers). It's easy to write
-your [own matchers](../../googlemock/docs/cook_book.md#NewMatchers) too.
-
-gMock is bundled with googletest, so you don't need to add any build dependency
-in order to take advantage of this. Just include `"testing/base/public/gmock.h"`
-and you're ready to go.
-
-### More String Assertions
-
-(Please read the [previous](#asserting-using-gmock-matchers) section first if
-you haven't.)
-
-You can use the gMock
-[string matchers](../../googlemock/docs/cheat_sheet.md#string-matchers) with
-`EXPECT_THAT()` or `ASSERT_THAT()` to do more string comparison tricks
-(sub-string, prefix, suffix, regular expression, and etc). For example,
-
-```c++
-using ::testing::HasSubstr;
-using ::testing::MatchesRegex;
-...
- ASSERT_THAT(foo_string, HasSubstr("needle"));
- EXPECT_THAT(bar_string, MatchesRegex("\\w*\\d+"));
-```
-
-If the string contains a well-formed HTML or XML document, you can check whether
-its DOM tree matches an
-[XPath expression](http://www.w3.org/TR/xpath/#contents):
-
-```c++
-// Currently still in //template/prototemplate/testing:xpath_matcher
-#include "template/prototemplate/testing/xpath_matcher.h"
-using prototemplate::testing::MatchesXPath;
-EXPECT_THAT(html_string, MatchesXPath("//a[text()='click here']"));
-```
-
-### Windows HRESULT assertions
-
-These assertions test for `HRESULT` success or failure.
-
-Fatal assertion | Nonfatal assertion | Verifies
--------------------------------------- | -------------------------------------- | --------
-`ASSERT_HRESULT_SUCCEEDED(expression)` | `EXPECT_HRESULT_SUCCEEDED(expression)` | `expression` is a success `HRESULT`
-`ASSERT_HRESULT_FAILED(expression)` | `EXPECT_HRESULT_FAILED(expression)` | `expression` is a failure `HRESULT`
-
-The generated output contains the human-readable error message associated with
-the `HRESULT` code returned by `expression`.
-
-You might use them like this:
-
-```c++
-CComPtr<IShellDispatch2> shell;
-ASSERT_HRESULT_SUCCEEDED(shell.CoCreateInstance(L"Shell.Application"));
-CComVariant empty;
-ASSERT_HRESULT_SUCCEEDED(shell->ShellExecute(CComBSTR(url), empty, empty, empty, empty));
-```
-
-### Type Assertions
-
-You can call the function
-
-```c++
-::testing::StaticAssertTypeEq<T1, T2>();
-```
-
-to assert that types `T1` and `T2` are the same. The function does nothing if
-the assertion is satisfied. If the types are different, the function call will
-fail to compile, the compiler error message will say that
-`type1 and type2 are not the same type` and most likely (depending on the compiler)
-show you the actual values of `T1` and `T2`. This is mainly useful inside
-template code.
-
-**Caveat**: When used inside a member function of a class template or a function
-template, `StaticAssertTypeEq<T1, T2>()` is effective only if the function is
-instantiated. For example, given:
-
-```c++
-template <typename T> class Foo {
- public:
- void Bar() { ::testing::StaticAssertTypeEq<int, T>(); }
-};
-```
-
-the code:
-
-```c++
-void Test1() { Foo<bool> foo; }
-```
-
-will not generate a compiler error, as `Foo<bool>::Bar()` is never actually
-instantiated. Instead, you need:
-
-```c++
-void Test2() { Foo<bool> foo; foo.Bar(); }
-```
-
-to cause a compiler error.
-
-### Assertion Placement
-
-You can use assertions in any C++ function. In particular, it doesn't have to be
-a method of the test fixture class. The one constraint is that assertions that
-generate a fatal failure (`FAIL*` and `ASSERT_*`) can only be used in
-void-returning functions. This is a consequence of Google's not using
-exceptions. By placing it in a non-void function you'll get a confusing compile
-error like `"error: void value not ignored as it ought to be"` or `"cannot
-initialize return object of type 'bool' with an rvalue of type 'void'"` or
-`"error: no viable conversion from 'void' to 'string'"`.
-
-If you need to use fatal assertions in a function that returns non-void, one
-option is to make the function return the value in an out parameter instead. For
-example, you can rewrite `T2 Foo(T1 x)` to `void Foo(T1 x, T2* result)`. You
-need to make sure that `*result` contains some sensible value even when the
-function returns prematurely. As the function now returns `void`, you can use
-any assertion inside of it.
-
-If changing the function's type is not an option, you should just use assertions
-that generate non-fatal failures, such as `ADD_FAILURE*` and `EXPECT_*`.
-
-NOTE: Constructors and destructors are not considered void-returning functions,
-according to the C++ language specification, and so you may not use fatal
-assertions in them; you'll get a compilation error if you try. Instead, either
-call `abort` and crash the entire test executable, or put the fatal assertion in
-a `SetUp`/`TearDown` function; see
-[constructor/destructor vs. `SetUp`/`TearDown`](faq.md#CtorVsSetUp)
-
-WARNING: A fatal assertion in a helper function (private void-returning method)
-called from a constructor or destructor does not does not terminate the current
-test, as your intuition might suggest: it merely returns from the constructor or
-destructor early, possibly leaving your object in a partially-constructed or
-partially-destructed state! You almost certainly want to `abort` or use
-`SetUp`/`TearDown` instead.
-
-## Teaching googletest How to Print Your Values
-
-When a test assertion such as `EXPECT_EQ` fails, googletest prints the argument
-values to help you debug. It does this using a user-extensible value printer.
-
-This printer knows how to print built-in C++ types, native arrays, STL
-containers, and any type that supports the `<<` operator. For other types, it
-prints the raw bytes in the value and hopes that you the user can figure it out.
-
-As mentioned earlier, the printer is *extensible*. That means you can teach it
-to do a better job at printing your particular type than to dump the bytes. To
-do that, define `<<` for your type:
-
-```c++
-#include <ostream>
-
-namespace foo {
-
-class Bar { // We want googletest to be able to print instances of this.
-...
- // Create a free inline friend function.
- friend std::ostream& operator<<(std::ostream& os, const Bar& bar) {
- return os << bar.DebugString(); // whatever needed to print bar to os
- }
-};
-
-// If you can't declare the function in the class it's important that the
-// << operator is defined in the SAME namespace that defines Bar. C++'s look-up
-// rules rely on that.
-std::ostream& operator<<(std::ostream& os, const Bar& bar) {
- return os << bar.DebugString(); // whatever needed to print bar to os
-}
-
-} // namespace foo
-```
-
-Sometimes, this might not be an option: your team may consider it bad style to
-have a `<<` operator for `Bar`, or `Bar` may already have a `<<` operator that
-doesn't do what you want (and you cannot change it). If so, you can instead
-define a `PrintTo()` function like this:
-
-```c++
-#include <ostream>
-
-namespace foo {
-
-class Bar {
- ...
- friend void PrintTo(const Bar& bar, std::ostream* os) {
- *os << bar.DebugString(); // whatever needed to print bar to os
- }
-};
-
-// If you can't declare the function in the class it's important that PrintTo()
-// is defined in the SAME namespace that defines Bar. C++'s look-up rules rely
-// on that.
-void PrintTo(const Bar& bar, std::ostream* os) {
- *os << bar.DebugString(); // whatever needed to print bar to os
-}
-
-} // namespace foo
-```
-
-If you have defined both `<<` and `PrintTo()`, the latter will be used when
-googletest is concerned. This allows you to customize how the value appears in
-googletest's output without affecting code that relies on the behavior of its
-`<<` operator.
-
-If you want to print a value `x` using googletest's value printer yourself, just
-call `::testing::PrintToString(x)`, which returns an `std::string`:
-
-```c++
-vector<pair<Bar, int> > bar_ints = GetBarIntVector();
-
-EXPECT_TRUE(IsCorrectBarIntVector(bar_ints))
- << "bar_ints = " << ::testing::PrintToString(bar_ints);
-```
-
-## Death Tests
-
-In many applications, there are assertions that can cause application failure if
-a condition is not met. These sanity checks, which ensure that the program is in
-a known good state, are there to fail at the earliest possible time after some
-program state is corrupted. If the assertion checks the wrong condition, then
-the program may proceed in an erroneous state, which could lead to memory
-corruption, security holes, or worse. Hence it is vitally important to test that
-such assertion statements work as expected.
-
-Since these precondition checks cause the processes to die, we call such tests
-_death tests_. More generally, any test that checks that a program terminates
-(except by throwing an exception) in an expected fashion is also a death test.
-
-Note that if a piece of code throws an exception, we don't consider it "death"
-for the purpose of death tests, as the caller of the code could catch the
-exception and avoid the crash. If you want to verify exceptions thrown by your
-code, see [Exception Assertions](#ExceptionAssertions).
-
-If you want to test `EXPECT_*()/ASSERT_*()` failures in your test code, see
-Catching Failures
-
-### How to Write a Death Test
-
-googletest has the following macros to support death tests:
-
-Fatal assertion | Nonfatal assertion | Verifies
------------------------------------------------- | ------------------------------------------------ | --------
-`ASSERT_DEATH(statement, matcher);` | `EXPECT_DEATH(statement, matcher);` | `statement` crashes with the given error
-`ASSERT_DEATH_IF_SUPPORTED(statement, matcher);` | `EXPECT_DEATH_IF_SUPPORTED(statement, matcher);` | if death tests are supported, verifies that `statement` crashes with the given error; otherwise verifies nothing
-`ASSERT_EXIT(statement, predicate, matcher);` | `EXPECT_EXIT(statement, predicate, matcher);` | `statement` exits with the given error, and its exit code matches `predicate`
-
-where `statement` is a statement that is expected to cause the process to die,
-`predicate` is a function or function object that evaluates an integer exit
-status, and `matcher` is either a GMock matcher matching a `const std::string&`
-or a (Perl) regular expression - either of which is matched against the stderr
-output of `statement`. For legacy reasons, a bare string (i.e. with no matcher)
-is interpreted as `ContainsRegex(str)`, **not** `Eq(str)`. Note that `statement`
-can be *any valid statement* (including *compound statement*) and doesn't have
-to be an expression.
-
-As usual, the `ASSERT` variants abort the current test function, while the
-`EXPECT` variants do not.
-
-> NOTE: We use the word "crash" here to mean that the process terminates with a
-> *non-zero* exit status code. There are two possibilities: either the process
-> has called `exit()` or `_exit()` with a non-zero value, or it may be killed by
-> a signal.
->
-> This means that if `*statement*` terminates the process with a 0 exit code, it
-> is *not* considered a crash by `EXPECT_DEATH`. Use `EXPECT_EXIT` instead if
-> this is the case, or if you want to restrict the exit code more precisely.
-
-A predicate here must accept an `int` and return a `bool`. The death test
-succeeds only if the predicate returns `true`. googletest defines a few
-predicates that handle the most common cases:
-
-```c++
-::testing::ExitedWithCode(exit_code)
-```
-
-This expression is `true` if the program exited normally with the given exit
-code.
-
-```c++
-::testing::KilledBySignal(signal_number) // Not available on Windows.
-```
-
-This expression is `true` if the program was killed by the given signal.
-
-The `*_DEATH` macros are convenient wrappers for `*_EXIT` that use a predicate
-that verifies the process' exit code is non-zero.
-
-Note that a death test only cares about three things:
-
-1. does `statement` abort or exit the process?
-2. (in the case of `ASSERT_EXIT` and `EXPECT_EXIT`) does the exit status
- satisfy `predicate`? Or (in the case of `ASSERT_DEATH` and `EXPECT_DEATH`)
- is the exit status non-zero? And
-3. does the stderr output match `regex`?
-
-In particular, if `statement` generates an `ASSERT_*` or `EXPECT_*` failure, it
-will **not** cause the death test to fail, as googletest assertions don't abort
-the process.
-
-To write a death test, simply use one of the above macros inside your test
-function. For example,
-
-```c++
-TEST(MyDeathTest, Foo) {
- // This death test uses a compound statement.
- ASSERT_DEATH({
- int n = 5;
- Foo(&n);
- }, "Error on line .* of Foo()");
-}
-
-TEST(MyDeathTest, NormalExit) {
- EXPECT_EXIT(NormalExit(), ::testing::ExitedWithCode(0), "Success");
-}
-
-TEST(MyDeathTest, KillMyself) {
- EXPECT_EXIT(KillMyself(), ::testing::KilledBySignal(SIGKILL),
- "Sending myself unblockable signal");
-}
-```
-
-verifies that:
-
-* calling `Foo(5)` causes the process to die with the given error message,
-* calling `NormalExit()` causes the process to print `"Success"` to stderr and
- exit with exit code 0, and
-* calling `KillMyself()` kills the process with signal `SIGKILL`.
-
-The test function body may contain other assertions and statements as well, if
-necessary.
-
-### Death Test Naming
-
-IMPORTANT: We strongly recommend you to follow the convention of naming your
-**test suite** (not test) `*DeathTest` when it contains a death test, as
-demonstrated in the above example. The
-[Death Tests And Threads](#death-tests-and-threads) section below explains why.
-
-If a test fixture class is shared by normal tests and death tests, you can use
-`using` or `typedef` to introduce an alias for the fixture class and avoid
-duplicating its code:
-
-```c++
-class FooTest : public ::testing::Test { ... };
-
-using FooDeathTest = FooTest;
-
-TEST_F(FooTest, DoesThis) {
- // normal test
-}
-
-TEST_F(FooDeathTest, DoesThat) {
- // death test
-}
-```
-
-### Regular Expression Syntax
-
-On POSIX systems (e.g. Linux, Cygwin, and Mac), googletest uses the
-[POSIX extended regular expression](http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_04)
-syntax. To learn about this syntax, you may want to read this
-[Wikipedia entry](http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions).
-
-On Windows, googletest uses its own simple regular expression implementation. It
-lacks many features. For example, we don't support union (`"x|y"`), grouping
-(`"(xy)"`), brackets (`"[xy]"`), and repetition count (`"x{5,7}"`), among
-others. Below is what we do support (`A` denotes a literal character, period
-(`.`), or a single `\\ ` escape sequence; `x` and `y` denote regular
-expressions.):
-
-Expression | Meaning
----------- | --------------------------------------------------------------
-`c` | matches any literal character `c`
-`\\d` | matches any decimal digit
-`\\D` | matches any character that's not a decimal digit
-`\\f` | matches `\f`
-`\\n` | matches `\n`
-`\\r` | matches `\r`
-`\\s` | matches any ASCII whitespace, including `\n`
-`\\S` | matches any character that's not a whitespace
-`\\t` | matches `\t`
-`\\v` | matches `\v`
-`\\w` | matches any letter, `_`, or decimal digit
-`\\W` | matches any character that `\\w` doesn't match
-`\\c` | matches any literal character `c`, which must be a punctuation
-`.` | matches any single character except `\n`
-`A?` | matches 0 or 1 occurrences of `A`
-`A*` | matches 0 or many occurrences of `A`
-`A+` | matches 1 or many occurrences of `A`
-`^` | matches the beginning of a string (not that of each line)
-`$` | matches the end of a string (not that of each line)
-`xy` | matches `x` followed by `y`
-
-To help you determine which capability is available on your system, googletest
-defines macros to govern which regular expression it is using. The macros are:
-`GTEST_USES_SIMPLE_RE=1` or `GTEST_USES_POSIX_RE=1`. If you want your death
-tests to work in all cases, you can either `#if` on these macros or use the more
-limited syntax only.
-
-### How It Works
-
-Under the hood, `ASSERT_EXIT()` spawns a new process and executes the death test
-statement in that process. The details of how precisely that happens depend on
-the platform and the variable ::testing::GTEST_FLAG(death_test_style) (which is
-initialized from the command-line flag `--gtest_death_test_style`).
-
-* On POSIX systems, `fork()` (or `clone()` on Linux) is used to spawn the
- child, after which:
- * If the variable's value is `"fast"`, the death test statement is
- immediately executed.
- * If the variable's value is `"threadsafe"`, the child process re-executes
- the unit test binary just as it was originally invoked, but with some
- extra flags to cause just the single death test under consideration to
- be run.
-* On Windows, the child is spawned using the `CreateProcess()` API, and
- re-executes the binary to cause just the single death test under
- consideration to be run - much like the `threadsafe` mode on POSIX.
-
-Other values for the variable are illegal and will cause the death test to fail.
-Currently, the flag's default value is **"fast"**
-
-1. the child's exit status satisfies the predicate, and
-2. the child's stderr matches the regular expression.
-
-If the death test statement runs to completion without dying, the child process
-will nonetheless terminate, and the assertion fails.
-
-### Death Tests And Threads
-
-The reason for the two death test styles has to do with thread safety. Due to
-well-known problems with forking in the presence of threads, death tests should
-be run in a single-threaded context. Sometimes, however, it isn't feasible to
-arrange that kind of environment. For example, statically-initialized modules
-may start threads before main is ever reached. Once threads have been created,
-it may be difficult or impossible to clean them up.
-
-googletest has three features intended to raise awareness of threading issues.
-
-1. A warning is emitted if multiple threads are running when a death test is
- encountered.
-2. Test suites with a name ending in "DeathTest" are run before all other
- tests.
-3. It uses `clone()` instead of `fork()` to spawn the child process on Linux
- (`clone()` is not available on Cygwin and Mac), as `fork()` is more likely
- to cause the child to hang when the parent process has multiple threads.
-
-It's perfectly fine to create threads inside a death test statement; they are
-executed in a separate process and cannot affect the parent.
-
-### Death Test Styles
-
-The "threadsafe" death test style was introduced in order to help mitigate the
-risks of testing in a possibly multithreaded environment. It trades increased
-test execution time (potentially dramatically so) for improved thread safety.
-
-The automated testing framework does not set the style flag. You can choose a
-particular style of death tests by setting the flag programmatically:
-
-```c++
-testing::FLAGS_gtest_death_test_style="threadsafe"
-```
-
-You can do this in `main()` to set the style for all death tests in the binary,
-or in individual tests. Recall that flags are saved before running each test and
-restored afterwards, so you need not do that yourself. For example:
-
-```c++
-int main(int argc, char** argv) {
- InitGoogle(argv[0], &argc, &argv, true);
- ::testing::FLAGS_gtest_death_test_style = "fast";
- return RUN_ALL_TESTS();
-}
-
-TEST(MyDeathTest, TestOne) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- // This test is run in the "threadsafe" style:
- ASSERT_DEATH(ThisShouldDie(), "");
-}
-
-TEST(MyDeathTest, TestTwo) {
- // This test is run in the "fast" style:
- ASSERT_DEATH(ThisShouldDie(), "");
-}
-```
-
-### Caveats
-
-The `statement` argument of `ASSERT_EXIT()` can be any valid C++ statement. If
-it leaves the current function via a `return` statement or by throwing an
-exception, the death test is considered to have failed. Some googletest macros
-may return from the current function (e.g. `ASSERT_TRUE()`), so be sure to avoid
-them in `statement`.
-
-Since `statement` runs in the child process, any in-memory side effect (e.g.
-modifying a variable, releasing memory, etc) it causes will *not* be observable
-in the parent process. In particular, if you release memory in a death test,
-your program will fail the heap check as the parent process will never see the
-memory reclaimed. To solve this problem, you can
-
-1. try not to free memory in a death test;
-2. free the memory again in the parent process; or
-3. do not use the heap checker in your program.
-
-Due to an implementation detail, you cannot place multiple death test assertions
-on the same line; otherwise, compilation will fail with an unobvious error
-message.
-
-Despite the improved thread safety afforded by the "threadsafe" style of death
-test, thread problems such as deadlock are still possible in the presence of
-handlers registered with `pthread_atfork(3)`.
-
-
-## Using Assertions in Sub-routines
-
-### Adding Traces to Assertions
-
-If a test sub-routine is called from several places, when an assertion inside it
-fails, it can be hard to tell which invocation of the sub-routine the failure is
-from. You can alleviate this problem using extra logging or custom failure
-messages, but that usually clutters up your tests. A better solution is to use
-the `SCOPED_TRACE` macro or the `ScopedTrace` utility:
-
-```c++
-SCOPED_TRACE(message);
-ScopedTrace trace("file_path", line_number, message);
-```
-
-where `message` can be anything streamable to `std::ostream`. `SCOPED_TRACE`
-macro will cause the current file name, line number, and the given message to be
-added in every failure message. `ScopedTrace` accepts explicit file name and
-line number in arguments, which is useful for writing test helpers. The effect
-will be undone when the control leaves the current lexical scope.
-
-For example,
-
-```c++
-10: void Sub1(int n) {
-11: EXPECT_EQ(Bar(n), 1);
-12: EXPECT_EQ(Bar(n + 1), 2);
-13: }
-14:
-15: TEST(FooTest, Bar) {
-16: {
-17: SCOPED_TRACE("A"); // This trace point will be included in
-18: // every failure in this scope.
-19: Sub1(1);
-20: }
-21: // Now it won't.
-22: Sub1(9);
-23: }
-```
-
-could result in messages like these:
-
-```none
-path/to/foo_test.cc:11: Failure
-Value of: Bar(n)
-Expected: 1
- Actual: 2
- Trace:
-path/to/foo_test.cc:17: A
-
-path/to/foo_test.cc:12: Failure
-Value of: Bar(n + 1)
-Expected: 2
- Actual: 3
-```
-
-Without the trace, it would've been difficult to know which invocation of
-`Sub1()` the two failures come from respectively. (You could add an extra
-message to each assertion in `Sub1()` to indicate the value of `n`, but that's
-tedious.)
-
-Some tips on using `SCOPED_TRACE`:
-
-1. With a suitable message, it's often enough to use `SCOPED_TRACE` at the
- beginning of a sub-routine, instead of at each call site.
-2. When calling sub-routines inside a loop, make the loop iterator part of the
- message in `SCOPED_TRACE` such that you can know which iteration the failure
- is from.
-3. Sometimes the line number of the trace point is enough for identifying the
- particular invocation of a sub-routine. In this case, you don't have to
- choose a unique message for `SCOPED_TRACE`. You can simply use `""`.
-4. You can use `SCOPED_TRACE` in an inner scope when there is one in the outer
- scope. In this case, all active trace points will be included in the failure
- messages, in reverse order they are encountered.
-5. The trace dump is clickable in Emacs - hit `return` on a line number and
- you'll be taken to that line in the source file!
-
-### Propagating Fatal Failures
-
-A common pitfall when using `ASSERT_*` and `FAIL*` is not understanding that
-when they fail they only abort the _current function_, not the entire test. For
-example, the following test will segfault:
-
-```c++
-void Subroutine() {
- // Generates a fatal failure and aborts the current function.
- ASSERT_EQ(1, 2);
-
- // The following won't be executed.
- ...
-}
-
-TEST(FooTest, Bar) {
- Subroutine(); // The intended behavior is for the fatal failure
- // in Subroutine() to abort the entire test.
-
- // The actual behavior: the function goes on after Subroutine() returns.
- int* p = NULL;
- *p = 3; // Segfault!
-}
-```
-
-To alleviate this, googletest provides three different solutions. You could use
-either exceptions, the `(ASSERT|EXPECT)_NO_FATAL_FAILURE` assertions or the
-`HasFatalFailure()` function. They are described in the following two
-subsections.
-
-#### Asserting on Subroutines with an exception
-
-The following code can turn ASSERT-failure into an exception:
-
-```c++
-class ThrowListener : public testing::EmptyTestEventListener {
- void OnTestPartResult(const testing::TestPartResult& result) override {
- if (result.type() == testing::TestPartResult::kFatalFailure) {
- throw testing::AssertionException(result);
- }
- }
-};
-int main(int argc, char** argv) {
- ...
- testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
- return RUN_ALL_TESTS();
-}
-```
-
-This listener should be added after other listeners if you have any, otherwise
-they won't see failed `OnTestPartResult`.
-
-#### Asserting on Subroutines
-
-As shown above, if your test calls a subroutine that has an `ASSERT_*` failure
-in it, the test will continue after the subroutine returns. This may not be what
-you want.
-
-Often people want fatal failures to propagate like exceptions. For that
-googletest offers the following macros:
-
-Fatal assertion | Nonfatal assertion | Verifies
-------------------------------------- | ------------------------------------- | --------
-`ASSERT_NO_FATAL_FAILURE(statement);` | `EXPECT_NO_FATAL_FAILURE(statement);` | `statement` doesn't generate any new fatal failures in the current thread.
-
-Only failures in the thread that executes the assertion are checked to determine
-the result of this type of assertions. If `statement` creates new threads,
-failures in these threads are ignored.
-
-Examples:
-
-```c++
-ASSERT_NO_FATAL_FAILURE(Foo());
-
-int i;
-EXPECT_NO_FATAL_FAILURE({
- i = Bar();
-});
-```
-
-Assertions from multiple threads are currently not supported on Windows.
-
-#### Checking for Failures in the Current Test
-
-`HasFatalFailure()` in the `::testing::Test` class returns `true` if an
-assertion in the current test has suffered a fatal failure. This allows
-functions to catch fatal failures in a sub-routine and return early.
-
-```c++
-class Test {
- public:
- ...
- static bool HasFatalFailure();
-};
-```
-
-The typical usage, which basically simulates the behavior of a thrown exception,
-is:
-
-```c++
-TEST(FooTest, Bar) {
- Subroutine();
- // Aborts if Subroutine() had a fatal failure.
- if (HasFatalFailure()) return;
-
- // The following won't be executed.
- ...
-}
-```
-
-If `HasFatalFailure()` is used outside of `TEST()` , `TEST_F()` , or a test
-fixture, you must add the `::testing::Test::` prefix, as in:
-
-```c++
-if (::testing::Test::HasFatalFailure()) return;
-```
-
-Similarly, `HasNonfatalFailure()` returns `true` if the current test has at
-least one non-fatal failure, and `HasFailure()` returns `true` if the current
-test has at least one failure of either kind.
-
-## Logging Additional Information
-
-In your test code, you can call `RecordProperty("key", value)` to log additional
-information, where `value` can be either a string or an `int`. The *last* value
-recorded for a key will be emitted to the
-[XML output](#generating-an-xml-report) if you specify one. For example, the
-test
-
-```c++
-TEST_F(WidgetUsageTest, MinAndMaxWidgets) {
- RecordProperty("MaximumWidgets", ComputeMaxUsage());
- RecordProperty("MinimumWidgets", ComputeMinUsage());
-}
-```
-
-will output XML like this:
-
-```xml
- ...
- <testcase name="MinAndMaxWidgets" status="run" time="0.006" classname="WidgetUsageTest" MaximumWidgets="12" MinimumWidgets="9" />
- ...
-```
-
-> NOTE:
->
-> * `RecordProperty()` is a static member of the `Test` class. Therefore it
-> needs to be prefixed with `::testing::Test::` if used outside of the
-> `TEST` body and the test fixture class.
-> * `*key*` must be a valid XML attribute name, and cannot conflict with the
-> ones already used by googletest (`name`, `status`, `time`, `classname`,
-> `type_param`, and `value_param`).
-> * Calling `RecordProperty()` outside of the lifespan of a test is allowed.
-> If it's called outside of a test but between a test suite's
-> `SetUpTestSuite()` and `TearDownTestSuite()` methods, it will be
-> attributed to the XML element for the test suite. If it's called outside
-> of all test suites (e.g. in a test environment), it will be attributed to
-> the top-level XML element.
-
-## Sharing Resources Between Tests in the Same Test Suite
-
-googletest creates a new test fixture object for each test in order to make
-tests independent and easier to debug. However, sometimes tests use resources
-that are expensive to set up, making the one-copy-per-test model prohibitively
-expensive.
-
-If the tests don't change the resource, there's no harm in their sharing a
-single resource copy. So, in addition to per-test set-up/tear-down, googletest
-also supports per-test-suite set-up/tear-down. To use it:
-
-1. In your test fixture class (say `FooTest` ), declare as `static` some member
- variables to hold the shared resources.
-2. Outside your test fixture class (typically just below it), define those
- member variables, optionally giving them initial values.
-3. In the same test fixture class, define a `static void SetUpTestSuite()`
- function (remember not to spell it as **`SetupTestSuite`** with a small
- `u`!) to set up the shared resources and a `static void TearDownTestSuite()`
- function to tear them down.
-
-That's it! googletest automatically calls `SetUpTestSuite()` before running the
-*first test* in the `FooTest` test suite (i.e. before creating the first
-`FooTest` object), and calls `TearDownTestSuite()` after running the *last test*
-in it (i.e. after deleting the last `FooTest` object). In between, the tests can
-use the shared resources.
-
-Remember that the test order is undefined, so your code can't depend on a test
-preceding or following another. Also, the tests must either not modify the state
-of any shared resource, or, if they do modify the state, they must restore the
-state to its original value before passing control to the next test.
-
-Here's an example of per-test-suite set-up and tear-down:
-
-```c++
-class FooTest : public ::testing::Test {
- protected:
- // Per-test-suite set-up.
- // Called before the first test in this test suite.
- // Can be omitted if not needed.
- static void SetUpTestSuite() {
- shared_resource_ = new ...;
- }
-
- // Per-test-suite tear-down.
- // Called after the last test in this test suite.
- // Can be omitted if not needed.
- static void TearDownTestSuite() {
- delete shared_resource_;
- shared_resource_ = NULL;
- }
-
- // You can define per-test set-up logic as usual.
- virtual void SetUp() { ... }
-
- // You can define per-test tear-down logic as usual.
- virtual void TearDown() { ... }
-
- // Some expensive resource shared by all tests.
- static T* shared_resource_;
-};
-
-T* FooTest::shared_resource_ = NULL;
-
-TEST_F(FooTest, Test1) {
- ... you can refer to shared_resource_ here ...
-}
-
-TEST_F(FooTest, Test2) {
- ... you can refer to shared_resource_ here ...
-}
-```
-
-NOTE: Though the above code declares `SetUpTestSuite()` protected, it may
-sometimes be necessary to declare it public, such as when using it with
-`TEST_P`.
-
-## Global Set-Up and Tear-Down
-
-Just as you can do set-up and tear-down at the test level and the test suite
-level, you can also do it at the test program level. Here's how.
-
-First, you subclass the `::testing::Environment` class to define a test
-environment, which knows how to set-up and tear-down:
-
-```c++
-class Environment : public ::testing::Environment {
- public:
- virtual ~Environment() {}
-
- // Override this to define how to set up the environment.
- void SetUp() override {}
-
- // Override this to define how to tear down the environment.
- void TearDown() override {}
-};
-```
-
-Then, you register an instance of your environment class with googletest by
-calling the `::testing::AddGlobalTestEnvironment()` function:
-
-```c++
-Environment* AddGlobalTestEnvironment(Environment* env);
-```
-
-Now, when `RUN_ALL_TESTS()` is called, it first calls the `SetUp()` method of
-each environment object, then runs the tests if none of the environments
-reported fatal failures and `GTEST_SKIP()` was not called. `RUN_ALL_TESTS()`
-always calls `TearDown()` with each environment object, regardless of whether or
-not the tests were run.
-
-It's OK to register multiple environment objects. In this suite, their `SetUp()`
-will be called in the order they are registered, and their `TearDown()` will be
-called in the reverse order.
-
-Note that googletest takes ownership of the registered environment objects.
-Therefore **do not delete them** by yourself.
-
-You should call `AddGlobalTestEnvironment()` before `RUN_ALL_TESTS()` is called,
-probably in `main()`. If you use `gtest_main`, you need to call this before
-`main()` starts for it to take effect. One way to do this is to define a global
-variable like this:
-
-```c++
-::testing::Environment* const foo_env =
- ::testing::AddGlobalTestEnvironment(new FooEnvironment);
-```
-
-However, we strongly recommend you to write your own `main()` and call
-`AddGlobalTestEnvironment()` there, as relying on initialization of global
-variables makes the code harder to read and may cause problems when you register
-multiple environments from different translation units and the environments have
-dependencies among them (remember that the compiler doesn't guarantee the order
-in which global variables from different translation units are initialized).
-
-## Value-Parameterized Tests
-
-*Value-parameterized tests* allow you to test your code with different
-parameters without writing multiple copies of the same test. This is useful in a
-number of situations, for example:
-
-* You have a piece of code whose behavior is affected by one or more
- command-line flags. You want to make sure your code performs correctly for
- various values of those flags.
-* You want to test different implementations of an OO interface.
-* You want to test your code over various inputs (a.k.a. data-driven testing).
- This feature is easy to abuse, so please exercise your good sense when doing
- it!
-
-### How to Write Value-Parameterized Tests
-
-To write value-parameterized tests, first you should define a fixture class. It
-must be derived from both `testing::Test` and `testing::WithParamInterface<T>`
-(the latter is a pure interface), where `T` is the type of your parameter
-values. For convenience, you can just derive the fixture class from
-`testing::TestWithParam<T>`, which itself is derived from both `testing::Test`
-and `testing::WithParamInterface<T>`. `T` can be any copyable type. If it's a
-raw pointer, you are responsible for managing the lifespan of the pointed
-values.
-
-NOTE: If your test fixture defines `SetUpTestSuite()` or `TearDownTestSuite()`
-they must be declared **public** rather than **protected** in order to use
-`TEST_P`.
-
-```c++
-class FooTest :
- public testing::TestWithParam<const char*> {
- // You can implement all the usual fixture class members here.
- // To access the test parameter, call GetParam() from class
- // TestWithParam<T>.
-};
-
-// Or, when you want to add parameters to a pre-existing fixture class:
-class BaseTest : public testing::Test {
- ...
-};
-class BarTest : public BaseTest,
- public testing::WithParamInterface<const char*> {
- ...
-};
-```
-
-Then, use the `TEST_P` macro to define as many test patterns using this fixture
-as you want. The `_P` suffix is for "parameterized" or "pattern", whichever you
-prefer to think.
-
-```c++
-TEST_P(FooTest, DoesBlah) {
- // Inside a test, access the test parameter with the GetParam() method
- // of the TestWithParam<T> class:
- EXPECT_TRUE(foo.Blah(GetParam()));
- ...
-}
-
-TEST_P(FooTest, HasBlahBlah) {
- ...
-}
-```
-
-Finally, you can use `INSTANTIATE_TEST_SUITE_P` to instantiate the test suite
-with any set of parameters you want. googletest defines a number of functions
-for generating test parameters. They return what we call (surprise!) *parameter
-generators*. Here is a summary of them, which are all in the `testing`
-namespace:
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-| Parameter Generator | Behavior |
-| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
-| `Range(begin, end [, step])` | Yields values `{begin, begin+step, begin+step+step, ...}`. The values do not include `end`. `step` defaults to 1. |
-| `Values(v1, v2, ..., vN)` | Yields values `{v1, v2, ..., vN}`. |
-| `ValuesIn(container)` and `ValuesIn(begin,end)` | Yields values from a C-style array, an STL-style container, or an iterator range `[begin, end)` |
-| `Bool()` | Yields sequence `{false, true}`. |
-| `Combine(g1, g2, ..., gN)` | Yields all combinations (Cartesian product) as std\:\:tuples of the values generated by the `N` generators. |
-
-<!-- mdformat on-->
-
-For more details, see the comments at the definitions of these functions.
-
-The following statement will instantiate tests from the `FooTest` test suite
-each with parameter values `"meeny"`, `"miny"`, and `"moe"`.
-
-```c++
-INSTANTIATE_TEST_SUITE_P(InstantiationName,
- FooTest,
- testing::Values("meeny", "miny", "moe"));
-```
-
-NOTE: The code above must be placed at global or namespace scope, not at
-function scope.
-
-NOTE: Don't forget this step! If you do your test will silently pass, but none
-of its suites will ever run!
-
-To distinguish different instances of the pattern (yes, you can instantiate it
-more than once), the first argument to `INSTANTIATE_TEST_SUITE_P` is a prefix
-that will be added to the actual test suite name. Remember to pick unique
-prefixes for different instantiations. The tests from the instantiation above
-will have these names:
-
-* `InstantiationName/FooTest.DoesBlah/0` for `"meeny"`
-* `InstantiationName/FooTest.DoesBlah/1` for `"miny"`
-* `InstantiationName/FooTest.DoesBlah/2` for `"moe"`
-* `InstantiationName/FooTest.HasBlahBlah/0` for `"meeny"`
-* `InstantiationName/FooTest.HasBlahBlah/1` for `"miny"`
-* `InstantiationName/FooTest.HasBlahBlah/2` for `"moe"`
-
-You can use these names in [`--gtest_filter`](#running-a-subset-of-the-tests).
-
-This statement will instantiate all tests from `FooTest` again, each with
-parameter values `"cat"` and `"dog"`:
-
-```c++
-const char* pets[] = {"cat", "dog"};
-INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest,
- testing::ValuesIn(pets));
-```
-
-The tests from the instantiation above will have these names:
-
-* `AnotherInstantiationName/FooTest.DoesBlah/0` for `"cat"`
-* `AnotherInstantiationName/FooTest.DoesBlah/1` for `"dog"`
-* `AnotherInstantiationName/FooTest.HasBlahBlah/0` for `"cat"`
-* `AnotherInstantiationName/FooTest.HasBlahBlah/1` for `"dog"`
-
-Please note that `INSTANTIATE_TEST_SUITE_P` will instantiate *all* tests in the
-given test suite, whether their definitions come before or *after* the
-`INSTANTIATE_TEST_SUITE_P` statement.
-
-You can see [sample7_unittest.cc] and [sample8_unittest.cc] for more examples.
-
-[sample7_unittest.cc]: ../samples/sample7_unittest.cc "Parameterized Test example"
-[sample8_unittest.cc]: ../samples/sample8_unittest.cc "Parameterized Test example with multiple parameters"
-
-### Creating Value-Parameterized Abstract Tests
-
-In the above, we define and instantiate `FooTest` in the *same* source file.
-Sometimes you may want to define value-parameterized tests in a library and let
-other people instantiate them later. This pattern is known as *abstract tests*.
-As an example of its application, when you are designing an interface you can
-write a standard suite of abstract tests (perhaps using a factory function as
-the test parameter) that all implementations of the interface are expected to
-pass. When someone implements the interface, they can instantiate your suite to
-get all the interface-conformance tests for free.
-
-To define abstract tests, you should organize your code like this:
-
-1. Put the definition of the parameterized test fixture class (e.g. `FooTest`)
- in a header file, say `foo_param_test.h`. Think of this as *declaring* your
- abstract tests.
-2. Put the `TEST_P` definitions in `foo_param_test.cc`, which includes
- `foo_param_test.h`. Think of this as *implementing* your abstract tests.
-
-Once they are defined, you can instantiate them by including `foo_param_test.h`,
-invoking `INSTANTIATE_TEST_SUITE_P()`, and depending on the library target that
-contains `foo_param_test.cc`. You can instantiate the same abstract test suite
-multiple times, possibly in different source files.
-
-### Specifying Names for Value-Parameterized Test Parameters
-
-The optional last argument to `INSTANTIATE_TEST_SUITE_P()` allows the user to
-specify a function or functor that generates custom test name suffixes based on
-the test parameters. The function should accept one argument of type
-`testing::TestParamInfo<class ParamType>`, and return `std::string`.
-
-`testing::PrintToStringParamName` is a builtin test suffix generator that
-returns the value of `testing::PrintToString(GetParam())`. It does not work for
-`std::string` or C strings.
-
-NOTE: test names must be non-empty, unique, and may only contain ASCII
-alphanumeric characters. In particular, they
-[should not contain underscores](faq.md#why-should-test-suite-names-and-test-names-not-contain-underscore)
-
-```c++
-class MyTestSuite : public testing::TestWithParam<int> {};
-
-TEST_P(MyTestSuite, MyTest)
-{
- std::cout << "Example Test Param: " << GetParam() << std::endl;
-}
-
-INSTANTIATE_TEST_SUITE_P(MyGroup, MyTestSuite, testing::Range(0, 10),
- testing::PrintToStringParamName());
-```
-
-Providing a custom functor allows for more control over test parameter name
-generation, especially for types where the automatic conversion does not
-generate helpful parameter names (e.g. strings as demonstrated above). The
-following example illustrates this for multiple parameters, an enumeration type
-and a string, and also demonstrates how to combine generators. It uses a lambda
-for conciseness:
-
-```c++
-enum class MyType { MY_FOO = 0, MY_BAR = 1 };
-
-class MyTestSuite : public testing::TestWithParam<std::tuple<MyType, string>> {
-};
-
-INSTANTIATE_TEST_SUITE_P(
- MyGroup, MyTestSuite,
- testing::Combine(
- testing::Values(MyType::VALUE_0, MyType::VALUE_1),
- testing::ValuesIn("", "")),
- [](const testing::TestParamInfo<MyTestSuite::ParamType>& info) {
- string name = absl::StrCat(
- std::get<0>(info.param) == MY_FOO ? "Foo" : "Bar", "_",
- std::get<1>(info.param));
- absl::c_replace_if(name, [](char c) { return !std::isalnum(c); }, '_');
- return name;
- });
-```
-
-## Typed Tests
-
-Suppose you have multiple implementations of the same interface and want to make
-sure that all of them satisfy some common requirements. Or, you may have defined
-several types that are supposed to conform to the same "concept" and you want to
-verify it. In both cases, you want the same test logic repeated for different
-types.
-
-While you can write one `TEST` or `TEST_F` for each type you want to test (and
-you may even factor the test logic into a function template that you invoke from
-the `TEST`), it's tedious and doesn't scale: if you want `m` tests over `n`
-types, you'll end up writing `m*n` `TEST`s.
-
-*Typed tests* allow you to repeat the same test logic over a list of types. You
-only need to write the test logic once, although you must know the type list
-when writing typed tests. Here's how you do it:
-
-First, define a fixture class template. It should be parameterized by a type.
-Remember to derive it from `::testing::Test`:
-
-```c++
-template <typename T>
-class FooTest : public ::testing::Test {
- public:
- ...
- typedef std::list<T> List;
- static T shared_;
- T value_;
-};
-```
-
-Next, associate a list of types with the test suite, which will be repeated for
-each type in the list:
-
-```c++
-using MyTypes = ::testing::Types<char, int, unsigned int>;
-TYPED_TEST_SUITE(FooTest, MyTypes);
-```
-
-The type alias (`using` or `typedef`) is necessary for the `TYPED_TEST_SUITE`
-macro to parse correctly. Otherwise the compiler will think that each comma in
-the type list introduces a new macro argument.
-
-Then, use `TYPED_TEST()` instead of `TEST_F()` to define a typed test for this
-test suite. You can repeat this as many times as you want:
-
-```c++
-TYPED_TEST(FooTest, DoesBlah) {
- // Inside a test, refer to the special name TypeParam to get the type
- // parameter. Since we are inside a derived class template, C++ requires
- // us to visit the members of FooTest via 'this'.
- TypeParam n = this->value_;
-
- // To visit static members of the fixture, add the 'TestFixture::'
- // prefix.
- n += TestFixture::shared_;
-
- // To refer to typedefs in the fixture, add the 'typename TestFixture::'
- // prefix. The 'typename' is required to satisfy the compiler.
- typename TestFixture::List values;
-
- values.push_back(n);
- ...
-}
-
-TYPED_TEST(FooTest, HasPropertyA) { ... }
-```
-
-You can see [sample6_unittest.cc] for a complete example.
-
-[sample6_unittest.cc]: ../samples/sample6_unittest.cc "Typed Test example"
-
-## Type-Parameterized Tests
-
-*Type-parameterized tests* are like typed tests, except that they don't require
-you to know the list of types ahead of time. Instead, you can define the test
-logic first and instantiate it with different type lists later. You can even
-instantiate it more than once in the same program.
-
-If you are designing an interface or concept, you can define a suite of
-type-parameterized tests to verify properties that any valid implementation of
-the interface/concept should have. Then, the author of each implementation can
-just instantiate the test suite with their type to verify that it conforms to
-the requirements, without having to write similar tests repeatedly. Here's an
-example:
-
-First, define a fixture class template, as we did with typed tests:
-
-```c++
-template <typename T>
-class FooTest : public ::testing::Test {
- ...
-};
-```
-
-Next, declare that you will define a type-parameterized test suite:
-
-```c++
-TYPED_TEST_SUITE_P(FooTest);
-```
-
-Then, use `TYPED_TEST_P()` to define a type-parameterized test. You can repeat
-this as many times as you want:
-
-```c++
-TYPED_TEST_P(FooTest, DoesBlah) {
- // Inside a test, refer to TypeParam to get the type parameter.
- TypeParam n = 0;
- ...
-}
-
-TYPED_TEST_P(FooTest, HasPropertyA) { ... }
-```
-
-Now the tricky part: you need to register all test patterns using the
-`REGISTER_TYPED_TEST_SUITE_P` macro before you can instantiate them. The first
-argument of the macro is the test suite name; the rest are the names of the
-tests in this test suite:
-
-```c++
-REGISTER_TYPED_TEST_SUITE_P(FooTest,
- DoesBlah, HasPropertyA);
-```
-
-Finally, you are free to instantiate the pattern with the types you want. If you
-put the above code in a header file, you can `#include` it in multiple C++
-source files and instantiate it multiple times.
-
-```c++
-typedef ::testing::Types<char, int, unsigned int> MyTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
-```
-
-To distinguish different instances of the pattern, the first argument to the
-`INSTANTIATE_TYPED_TEST_SUITE_P` macro is a prefix that will be added to the
-actual test suite name. Remember to pick unique prefixes for different
-instances.
-
-In the special case where the type list contains only one type, you can write
-that type directly without `::testing::Types<...>`, like this:
-
-```c++
-INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
-```
-
-You can see [sample6_unittest.cc] for a complete example.
-
-## Testing Private Code
-
-If you change your software's internal implementation, your tests should not
-break as long as the change is not observable by users. Therefore, **per the
-black-box testing principle, most of the time you should test your code through
-its public interfaces.**
-
-**If you still find yourself needing to test internal implementation code,
-consider if there's a better design.** The desire to test internal
-implementation is often a sign that the class is doing too much. Consider
-extracting an implementation class, and testing it. Then use that implementation
-class in the original class.
-
-If you absolutely have to test non-public interface code though, you can. There
-are two cases to consider:
-
-* Static functions ( *not* the same as static member functions!) or unnamed
- namespaces, and
-* Private or protected class members
-
-To test them, we use the following special techniques:
-
-* Both static functions and definitions/declarations in an unnamed namespace
- are only visible within the same translation unit. To test them, you can
- `#include` the entire `.cc` file being tested in your `*_test.cc` file.
- (#including `.cc` files is not a good way to reuse code - you should not do
- this in production code!)
-
- However, a better approach is to move the private code into the
- `foo::internal` namespace, where `foo` is the namespace your project
- normally uses, and put the private declarations in a `*-internal.h` file.
- Your production `.cc` files and your tests are allowed to include this
- internal header, but your clients are not. This way, you can fully test your
- internal implementation without leaking it to your clients.
-
-* Private class members are only accessible from within the class or by
- friends. To access a class' private members, you can declare your test
- fixture as a friend to the class and define accessors in your fixture. Tests
- using the fixture can then access the private members of your production
- class via the accessors in the fixture. Note that even though your fixture
- is a friend to your production class, your tests are not automatically
- friends to it, as they are technically defined in sub-classes of the
- fixture.
-
- Another way to test private members is to refactor them into an
- implementation class, which is then declared in a `*-internal.h` file. Your
- clients aren't allowed to include this header but your tests can. Such is
- called the
- [Pimpl](https://www.gamedev.net/articles/programming/general-and-gameplay-programming/the-c-pimpl-r1794/)
- (Private Implementation) idiom.
-
- Or, you can declare an individual test as a friend of your class by adding
- this line in the class body:
-
- ```c++
- FRIEND_TEST(TestSuiteName, TestName);
- ```
-
- For example,
-
- ```c++
- // foo.h
- class Foo {
- ...
- private:
- FRIEND_TEST(FooTest, BarReturnsZeroOnNull);
-
- int Bar(void* x);
- };
-
- // foo_test.cc
- ...
- TEST(FooTest, BarReturnsZeroOnNull) {
- Foo foo;
- EXPECT_EQ(foo.Bar(NULL), 0); // Uses Foo's private member Bar().
- }
- ```
-
- Pay special attention when your class is defined in a namespace, as you
- should define your test fixtures and tests in the same namespace if you want
- them to be friends of your class. For example, if the code to be tested
- looks like:
-
- ```c++
- namespace my_namespace {
-
- class Foo {
- friend class FooTest;
- FRIEND_TEST(FooTest, Bar);
- FRIEND_TEST(FooTest, Baz);
- ... definition of the class Foo ...
- };
-
- } // namespace my_namespace
- ```
-
- Your test code should be something like:
-
- ```c++
- namespace my_namespace {
-
- class FooTest : public ::testing::Test {
- protected:
- ...
- };
-
- TEST_F(FooTest, Bar) { ... }
- TEST_F(FooTest, Baz) { ... }
-
- } // namespace my_namespace
- ```
-
-## "Catching" Failures
-
-If you are building a testing utility on top of googletest, you'll want to test
-your utility. What framework would you use to test it? googletest, of course.
-
-The challenge is to verify that your testing utility reports failures correctly.
-In frameworks that report a failure by throwing an exception, you could catch
-the exception and assert on it. But googletest doesn't use exceptions, so how do
-we test that a piece of code generates an expected failure?
-
-gunit-spi.h contains some constructs to do this. After #including this header,
-you can use
-
-```c++
- EXPECT_FATAL_FAILURE(statement, substring);
-```
-
-to assert that `statement` generates a fatal (e.g. `ASSERT_*`) failure in the
-current thread whose message contains the given `substring`, or use
-
-```c++
- EXPECT_NONFATAL_FAILURE(statement, substring);
-```
-
-if you are expecting a non-fatal (e.g. `EXPECT_*`) failure.
-
-Only failures in the current thread are checked to determine the result of this
-type of expectations. If `statement` creates new threads, failures in these
-threads are also ignored. If you want to catch failures in other threads as
-well, use one of the following macros instead:
-
-```c++
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substring);
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substring);
-```
-
-NOTE: Assertions from multiple threads are currently not supported on Windows.
-
-For technical reasons, there are some caveats:
-
-1. You cannot stream a failure message to either macro.
-
-2. `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()` cannot reference
- local non-static variables or non-static members of `this` object.
-
-3. `statement` in `EXPECT_FATAL_FAILURE{_ON_ALL_THREADS}()` cannot return a
- value.
-
-## Registering tests programmatically
-
-The `TEST` macros handle the vast majority of all use cases, but there are few
-were runtime registration logic is required. For those cases, the framework
-provides the `::testing::RegisterTest` that allows callers to register arbitrary
-tests dynamically.
-
-This is an advanced API only to be used when the `TEST` macros are insufficient.
-The macros should be preferred when possible, as they avoid most of the
-complexity of calling this function.
-
-It provides the following signature:
-
-```c++
-template <typename Factory>
-TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
- const char* type_param, const char* value_param,
- const char* file, int line, Factory factory);
-```
-
-The `factory` argument is a factory callable (move-constructible) object or
-function pointer that creates a new instance of the Test object. It handles
-ownership to the caller. The signature of the callable is `Fixture*()`, where
-`Fixture` is the test fixture class for the test. All tests registered with the
-same `test_suite_name` must return the same fixture type. This is checked at
-runtime.
-
-The framework will infer the fixture class from the factory and will call the
-`SetUpTestSuite` and `TearDownTestSuite` for it.
-
-Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is
-undefined.
-
-Use case example:
-
-```c++
-class MyFixture : public ::testing::Test {
- public:
- // All of these optional, just like in regular macro usage.
- static void SetUpTestSuite() { ... }
- static void TearDownTestSuite() { ... }
- void SetUp() override { ... }
- void TearDown() override { ... }
-};
-
-class MyTest : public MyFixture {
- public:
- explicit MyTest(int data) : data_(data) {}
- void TestBody() override { ... }
-
- private:
- int data_;
-};
-
-void RegisterMyTests(const std::vector<int>& values) {
- for (int v : values) {
- ::testing::RegisterTest(
- "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr,
- std::to_string(v).c_str(),
- __FILE__, __LINE__,
- // Important to use the fixture type as the return type here.
- [=]() -> MyFixture* { return new MyTest(v); });
- }
-}
-...
-int main(int argc, char** argv) {
- std::vector<int> values_to_test = LoadValuesFromConfig();
- RegisterMyTests(values_to_test);
- ...
- return RUN_ALL_TESTS();
-}
-```
-## Getting the Current Test's Name
-
-Sometimes a function may need to know the name of the currently running test.
-For example, you may be using the `SetUp()` method of your test fixture to set
-the golden file name based on which test is running. The `::testing::TestInfo`
-class has this information:
-
-```c++
-namespace testing {
-
-class TestInfo {
- public:
- // Returns the test suite name and the test name, respectively.
- //
- // Do NOT delete or free the return value - it's managed by the
- // TestInfo class.
- const char* test_suite_name() const;
- const char* name() const;
-};
-
-}
-```
-
-To obtain a `TestInfo` object for the currently running test, call
-`current_test_info()` on the `UnitTest` singleton object:
-
-```c++
- // Gets information about the currently running test.
- // Do NOT delete the returned object - it's managed by the UnitTest class.
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
-
-
-
- printf("We are in test %s of test suite %s.\n",
- test_info->name(),
- test_info->test_suite_name());
-```
-
-`current_test_info()` returns a null pointer if no test is running. In
-particular, you cannot find the test suite name in `TestSuiteSetUp()`,
-`TestSuiteTearDown()` (where you know the test suite name implicitly), or
-functions called from them.
-
-## Extending googletest by Handling Test Events
-
-googletest provides an **event listener API** to let you receive notifications
-about the progress of a test program and test failures. The events you can
-listen to include the start and end of the test program, a test suite, or a test
-method, among others. You may use this API to augment or replace the standard
-console output, replace the XML output, or provide a completely different form
-of output, such as a GUI or a database. You can also use test events as
-checkpoints to implement a resource leak checker, for example.
-
-### Defining Event Listeners
-
-To define a event listener, you subclass either testing::TestEventListener or
-testing::EmptyTestEventListener The former is an (abstract) interface, where
-*each pure virtual method can be overridden to handle a test event* (For
-example, when a test starts, the `OnTestStart()` method will be called.). The
-latter provides an empty implementation of all methods in the interface, such
-that a subclass only needs to override the methods it cares about.
-
-When an event is fired, its context is passed to the handler function as an
-argument. The following argument types are used:
-
-* UnitTest reflects the state of the entire test program,
-* TestSuite has information about a test suite, which can contain one or more
- tests,
-* TestInfo contains the state of a test, and
-* TestPartResult represents the result of a test assertion.
-
-An event handler function can examine the argument it receives to find out
-interesting information about the event and the test program's state.
-
-Here's an example:
-
-```c++
- class MinimalistPrinter : public ::testing::EmptyTestEventListener {
- // Called before a test starts.
- virtual void OnTestStart(const ::testing::TestInfo& test_info) {
- printf("*** Test %s.%s starting.\n",
- test_info.test_suite_name(), test_info.name());
- }
-
- // Called after a failed assertion or a SUCCESS().
- virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result) {
- printf("%s in %s:%d\n%s\n",
- test_part_result.failed() ? "*** Failure" : "Success",
- test_part_result.file_name(),
- test_part_result.line_number(),
- test_part_result.summary());
- }
-
- // Called after a test ends.
- virtual void OnTestEnd(const ::testing::TestInfo& test_info) {
- printf("*** Test %s.%s ending.\n",
- test_info.test_suite_name(), test_info.name());
- }
- };
-```
-
-### Using Event Listeners
-
-To use the event listener you have defined, add an instance of it to the
-googletest event listener list (represented by class TestEventListeners - note
-the "s" at the end of the name) in your `main()` function, before calling
-`RUN_ALL_TESTS()`:
-
-```c++
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- // Gets hold of the event listener list.
- ::testing::TestEventListeners& listeners =
- ::testing::UnitTest::GetInstance()->listeners();
- // Adds a listener to the end. googletest takes the ownership.
- listeners.Append(new MinimalistPrinter);
- return RUN_ALL_TESTS();
-}
-```
-
-There's only one problem: the default test result printer is still in effect, so
-its output will mingle with the output from your minimalist printer. To suppress
-the default printer, just release it from the event listener list and delete it.
-You can do so by adding one line:
-
-```c++
- ...
- delete listeners.Release(listeners.default_result_printer());
- listeners.Append(new MinimalistPrinter);
- return RUN_ALL_TESTS();
-```
-
-Now, sit back and enjoy a completely different output from your tests. For more
-details, see [sample9_unittest.cc].
-
-[sample9_unittest.cc]: ../samples/sample9_unittest.cc "Event listener example"
-
-You may append more than one listener to the list. When an `On*Start()` or
-`OnTestPartResult()` event is fired, the listeners will receive it in the order
-they appear in the list (since new listeners are added to the end of the list,
-the default text printer and the default XML generator will receive the event
-first). An `On*End()` event will be received by the listeners in the *reverse*
-order. This allows output by listeners added later to be framed by output from
-listeners added earlier.
-
-### Generating Failures in Listeners
-
-You may use failure-raising macros (`EXPECT_*()`, `ASSERT_*()`, `FAIL()`, etc)
-when processing an event. There are some restrictions:
-
-1. You cannot generate any failure in `OnTestPartResult()` (otherwise it will
- cause `OnTestPartResult()` to be called recursively).
-2. A listener that handles `OnTestPartResult()` is not allowed to generate any
- failure.
-
-When you add listeners to the listener list, you should put listeners that
-handle `OnTestPartResult()` *before* listeners that can generate failures. This
-ensures that failures generated by the latter are attributed to the right test
-by the former.
-
-See [sample10_unittest.cc] for an example of a failure-raising listener.
-
-[sample10_unittest.cc]: ../samples/sample10_unittest.cc "Failure-raising listener example"
-
-## Running Test Programs: Advanced Options
-
-googletest test programs are ordinary executables. Once built, you can run them
-directly and affect their behavior via the following environment variables
-and/or command line flags. For the flags to work, your programs must call
-`::testing::InitGoogleTest()` before calling `RUN_ALL_TESTS()`.
-
-To see a list of supported flags and their usage, please run your test program
-with the `--help` flag. You can also use `-h`, `-?`, or `/?` for short.
-
-If an option is specified both by an environment variable and by a flag, the
-latter takes precedence.
-
-### Selecting Tests
-
-#### Listing Test Names
-
-Sometimes it is necessary to list the available tests in a program before
-running them so that a filter may be applied if needed. Including the flag
-`--gtest_list_tests` overrides all other flags and lists tests in the following
-format:
-
-```none
-TestSuite1.
- TestName1
- TestName2
-TestSuite2.
- TestName
-```
-
-None of the tests listed are actually run if the flag is provided. There is no
-corresponding environment variable for this flag.
-
-#### Running a Subset of the Tests
-
-By default, a googletest program runs all tests the user has defined. Sometimes,
-you want to run only a subset of the tests (e.g. for debugging or quickly
-verifying a change). If you set the `GTEST_FILTER` environment variable or the
-`--gtest_filter` flag to a filter string, googletest will only run the tests
-whose full names (in the form of `TestSuiteName.TestName`) match the filter.
-
-The format of a filter is a '`:`'-separated list of wildcard patterns (called
-the *positive patterns*) optionally followed by a '`-`' and another
-'`:`'-separated pattern list (called the *negative patterns*). A test matches
-the filter if and only if it matches any of the positive patterns but does not
-match any of the negative patterns.
-
-A pattern may contain `'*'` (matches any string) or `'?'` (matches any single
-character). For convenience, the filter `'*-NegativePatterns'` can be also
-written as `'-NegativePatterns'`.
-
-For example:
-
-* `./foo_test` Has no flag, and thus runs all its tests.
-* `./foo_test --gtest_filter=*` Also runs everything, due to the single
- match-everything `*` value.
-* `./foo_test --gtest_filter=FooTest.*` Runs everything in test suite
- `FooTest` .
-* `./foo_test --gtest_filter=*Null*:*Constructor*` Runs any test whose full
- name contains either `"Null"` or `"Constructor"` .
-* `./foo_test --gtest_filter=-*DeathTest.*` Runs all non-death tests.
-* `./foo_test --gtest_filter=FooTest.*-FooTest.Bar` Runs everything in test
- suite `FooTest` except `FooTest.Bar`.
-* `./foo_test --gtest_filter=FooTest.*:BarTest.*-FooTest.Bar:BarTest.Foo` Runs
- everything in test suite `FooTest` except `FooTest.Bar` and everything in
- test suite `BarTest` except `BarTest.Foo`.
-
-#### Temporarily Disabling Tests
-
-If you have a broken test that you cannot fix right away, you can add the
-`DISABLED_` prefix to its name. This will exclude it from execution. This is
-better than commenting out the code or using `#if 0`, as disabled tests are
-still compiled (and thus won't rot).
-
-If you need to disable all tests in a test suite, you can either add `DISABLED_`
-to the front of the name of each test, or alternatively add it to the front of
-the test suite name.
-
-For example, the following tests won't be run by googletest, even though they
-will still be compiled:
-
-```c++
-// Tests that Foo does Abc.
-TEST(FooTest, DISABLED_DoesAbc) { ... }
-
-class DISABLED_BarTest : public ::testing::Test { ... };
-
-// Tests that Bar does Xyz.
-TEST_F(DISABLED_BarTest, DoesXyz) { ... }
-```
-
-NOTE: This feature should only be used for temporary pain-relief. You still have
-to fix the disabled tests at a later date. As a reminder, googletest will print
-a banner warning you if a test program contains any disabled tests.
-
-TIP: You can easily count the number of disabled tests you have using `gsearch`
-and/or `grep`. This number can be used as a metric for improving your test
-quality.
-
-#### Temporarily Enabling Disabled Tests
-
-To include disabled tests in test execution, just invoke the test program with
-the `--gtest_also_run_disabled_tests` flag or set the
-`GTEST_ALSO_RUN_DISABLED_TESTS` environment variable to a value other than `0`.
-You can combine this with the `--gtest_filter` flag to further select which
-disabled tests to run.
-
-### Repeating the Tests
-
-Once in a while you'll run into a test whose result is hit-or-miss. Perhaps it
-will fail only 1% of the time, making it rather hard to reproduce the bug under
-a debugger. This can be a major source of frustration.
-
-The `--gtest_repeat` flag allows you to repeat all (or selected) test methods in
-a program many times. Hopefully, a flaky test will eventually fail and give you
-a chance to debug. Here's how to use it:
-
-```none
-$ foo_test --gtest_repeat=1000
-Repeat foo_test 1000 times and don't stop at failures.
-
-$ foo_test --gtest_repeat=-1
-A negative count means repeating forever.
-
-$ foo_test --gtest_repeat=1000 --gtest_break_on_failure
-Repeat foo_test 1000 times, stopping at the first failure. This
-is especially useful when running under a debugger: when the test
-fails, it will drop into the debugger and you can then inspect
-variables and stacks.
-
-$ foo_test --gtest_repeat=1000 --gtest_filter=FooBar.*
-Repeat the tests whose name matches the filter 1000 times.
-```
-
-If your test program contains
-[global set-up/tear-down](#global-set-up-and-tear-down) code, it will be
-repeated in each iteration as well, as the flakiness may be in it. You can also
-specify the repeat count by setting the `GTEST_REPEAT` environment variable.
-
-### Shuffling the Tests
-
-You can specify the `--gtest_shuffle` flag (or set the `GTEST_SHUFFLE`
-environment variable to `1`) to run the tests in a program in a random order.
-This helps to reveal bad dependencies between tests.
-
-By default, googletest uses a random seed calculated from the current time.
-Therefore you'll get a different order every time. The console output includes
-the random seed value, such that you can reproduce an order-related test failure
-later. To specify the random seed explicitly, use the `--gtest_random_seed=SEED`
-flag (or set the `GTEST_RANDOM_SEED` environment variable), where `SEED` is an
-integer in the range [0, 99999]. The seed value 0 is special: it tells
-googletest to do the default behavior of calculating the seed from the current
-time.
-
-If you combine this with `--gtest_repeat=N`, googletest will pick a different
-random seed and re-shuffle the tests in each iteration.
-
-### Controlling Test Output
-
-#### Colored Terminal Output
-
-googletest can use colors in its terminal output to make it easier to spot the
-important information:
-
-<code>
-...<br/>
- <font color="green">[----------]</font><font color="black"> 1 test from
- FooTest</font><br/>
- <font color="green">[ RUN ]</font><font color="black">
- FooTest.DoesAbc</font><br/>
- <font color="green">[ OK ]</font><font color="black">
- FooTest.DoesAbc </font><br/>
- <font color="green">[----------]</font><font color="black">
- 2 tests from BarTest</font><br/>
- <font color="green">[ RUN ]</font><font color="black">
- BarTest.HasXyzProperty </font><br/>
- <font color="green">[ OK ]</font><font color="black">
- BarTest.HasXyzProperty</font><br/>
- <font color="green">[ RUN ]</font><font color="black">
- BarTest.ReturnsTrueOnSuccess ... some error messages ...</font><br/>
- <font color="red">[ FAILED ]</font><font color="black">
- BarTest.ReturnsTrueOnSuccess ...</font><br/>
- <font color="green">[==========]</font><font color="black">
- 30 tests from 14 test suites ran.</font><br/>
- <font color="green">[ PASSED ]</font><font color="black">
- 28 tests.</font><br/>
- <font color="red">[ FAILED ]</font><font color="black">
- 2 tests, listed below:</font><br/>
- <font color="red">[ FAILED ]</font><font color="black">
- BarTest.ReturnsTrueOnSuccess</font><br/>
- <font color="red">[ FAILED ]</font><font color="black">
- AnotherTest.DoesXyz<br/>
-<br/>
- 2 FAILED TESTS
- </font>
-</code>
-
-You can set the `GTEST_COLOR` environment variable or the `--gtest_color`
-command line flag to `yes`, `no`, or `auto` (the default) to enable colors,
-disable colors, or let googletest decide. When the value is `auto`, googletest
-will use colors if and only if the output goes to a terminal and (on non-Windows
-platforms) the `TERM` environment variable is set to `xterm` or `xterm-color`.
-
-#### Suppressing the Elapsed Time
-
-By default, googletest prints the time it takes to run each test. To disable
-that, run the test program with the `--gtest_print_time=0` command line flag, or
-set the GTEST_PRINT_TIME environment variable to `0`.
-
-#### Suppressing UTF-8 Text Output
-
-In case of assertion failures, googletest prints expected and actual values of
-type `string` both as hex-encoded strings as well as in readable UTF-8 text if
-they contain valid non-ASCII UTF-8 characters. If you want to suppress the UTF-8
-text because, for example, you don't have an UTF-8 compatible output medium, run
-the test program with `--gtest_print_utf8=0` or set the `GTEST_PRINT_UTF8`
-environment variable to `0`.
-
-
-
-#### Generating an XML Report
-
-googletest can emit a detailed XML report to a file in addition to its normal
-textual output. The report contains the duration of each test, and thus can help
-you identify slow tests. The report is also used by the http://unittest
-dashboard to show per-test-method error messages.
-
-To generate the XML report, set the `GTEST_OUTPUT` environment variable or the
-`--gtest_output` flag to the string `"xml:path_to_output_file"`, which will
-create the file at the given location. You can also just use the string `"xml"`,
-in which case the output can be found in the `test_detail.xml` file in the
-current directory.
-
-If you specify a directory (for example, `"xml:output/directory/"` on Linux or
-`"xml:output\directory\"` on Windows), googletest will create the XML file in
-that directory, named after the test executable (e.g. `foo_test.xml` for test
-program `foo_test` or `foo_test.exe`). If the file already exists (perhaps left
-over from a previous run), googletest will pick a different name (e.g.
-`foo_test_1.xml`) to avoid overwriting it.
-
-The report is based on the `junitreport` Ant task. Since that format was
-originally intended for Java, a little interpretation is required to make it
-apply to googletest tests, as shown here:
-
-```xml
-<testsuites name="AllTests" ...>
- <testsuite name="test_case_name" ...>
- <testcase name="test_name" ...>
- <failure message="..."/>
- <failure message="..."/>
- <failure message="..."/>
- </testcase>
- </testsuite>
-</testsuites>
-```
-
-* The root `<testsuites>` element corresponds to the entire test program.
-* `<testsuite>` elements correspond to googletest test suites.
-* `<testcase>` elements correspond to googletest test functions.
-
-For instance, the following program
-
-```c++
-TEST(MathTest, Addition) { ... }
-TEST(MathTest, Subtraction) { ... }
-TEST(LogicTest, NonContradiction) { ... }
-```
-
-could generate this report:
-
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="3" failures="1" errors="0" time="0.035" timestamp="2011-10-31T18:52:42" name="AllTests">
- <testsuite name="MathTest" tests="2" failures="1" errors="0" time="0.015">
- <testcase name="Addition" status="run" time="0.007" classname="">
- <failure message="Value of: add(1, 1)
 Actual: 3
Expected: 2" type="">...</failure>
- <failure message="Value of: add(1, -1)
 Actual: 1
Expected: 0" type="">...</failure>
- </testcase>
- <testcase name="Subtraction" status="run" time="0.005" classname="">
- </testcase>
- </testsuite>
- <testsuite name="LogicTest" tests="1" failures="0" errors="0" time="0.005">
- <testcase name="NonContradiction" status="run" time="0.005" classname="">
- </testcase>
- </testsuite>
-</testsuites>
-```
-
-Things to note:
-
-* The `tests` attribute of a `<testsuites>` or `<testsuite>` element tells how
- many test functions the googletest program or test suite contains, while the
- `failures` attribute tells how many of them failed.
-
-* The `time` attribute expresses the duration of the test, test suite, or
- entire test program in seconds.
-
-* The `timestamp` attribute records the local date and time of the test
- execution.
-
-* Each `<failure>` element corresponds to a single failed googletest
- assertion.
-
-#### Generating a JSON Report
-
-googletest can also emit a JSON report as an alternative format to XML. To
-generate the JSON report, set the `GTEST_OUTPUT` environment variable or the
-`--gtest_output` flag to the string `"json:path_to_output_file"`, which will
-create the file at the given location. You can also just use the string
-`"json"`, in which case the output can be found in the `test_detail.json` file
-in the current directory.
-
-The report format conforms to the following JSON Schema:
-
-```json
-{
- "$schema": "http://json-schema.org/schema#",
- "type": "object",
- "definitions": {
- "TestCase": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "tests": { "type": "integer" },
- "failures": { "type": "integer" },
- "disabled": { "type": "integer" },
- "time": { "type": "string" },
- "testsuite": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/TestInfo"
- }
- }
- }
- },
- "TestInfo": {
- "type": "object",
- "properties": {
- "name": { "type": "string" },
- "status": {
- "type": "string",
- "enum": ["RUN", "NOTRUN"]
- },
- "time": { "type": "string" },
- "classname": { "type": "string" },
- "failures": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/Failure"
- }
- }
- }
- },
- "Failure": {
- "type": "object",
- "properties": {
- "failures": { "type": "string" },
- "type": { "type": "string" }
- }
- }
- },
- "properties": {
- "tests": { "type": "integer" },
- "failures": { "type": "integer" },
- "disabled": { "type": "integer" },
- "errors": { "type": "integer" },
- "timestamp": {
- "type": "string",
- "format": "date-time"
- },
- "time": { "type": "string" },
- "name": { "type": "string" },
- "testsuites": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/TestCase"
- }
- }
- }
-}
-```
-
-The report uses the format that conforms to the following Proto3 using the
-[JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json):
-
-```proto
-syntax = "proto3";
-
-package googletest;
-
-import "google/protobuf/timestamp.proto";
-import "google/protobuf/duration.proto";
-
-message UnitTest {
- int32 tests = 1;
- int32 failures = 2;
- int32 disabled = 3;
- int32 errors = 4;
- google.protobuf.Timestamp timestamp = 5;
- google.protobuf.Duration time = 6;
- string name = 7;
- repeated TestCase testsuites = 8;
-}
-
-message TestCase {
- string name = 1;
- int32 tests = 2;
- int32 failures = 3;
- int32 disabled = 4;
- int32 errors = 5;
- google.protobuf.Duration time = 6;
- repeated TestInfo testsuite = 7;
-}
-
-message TestInfo {
- string name = 1;
- enum Status {
- RUN = 0;
- NOTRUN = 1;
- }
- Status status = 2;
- google.protobuf.Duration time = 3;
- string classname = 4;
- message Failure {
- string failures = 1;
- string type = 2;
- }
- repeated Failure failures = 5;
-}
-```
-
-For instance, the following program
-
-```c++
-TEST(MathTest, Addition) { ... }
-TEST(MathTest, Subtraction) { ... }
-TEST(LogicTest, NonContradiction) { ... }
-```
-
-could generate this report:
-
-```json
-{
- "tests": 3,
- "failures": 1,
- "errors": 0,
- "time": "0.035s",
- "timestamp": "2011-10-31T18:52:42Z",
- "name": "AllTests",
- "testsuites": [
- {
- "name": "MathTest",
- "tests": 2,
- "failures": 1,
- "errors": 0,
- "time": "0.015s",
- "testsuite": [
- {
- "name": "Addition",
- "status": "RUN",
- "time": "0.007s",
- "classname": "",
- "failures": [
- {
- "message": "Value of: add(1, 1)\n Actual: 3\nExpected: 2",
- "type": ""
- },
- {
- "message": "Value of: add(1, -1)\n Actual: 1\nExpected: 0",
- "type": ""
- }
- ]
- },
- {
- "name": "Subtraction",
- "status": "RUN",
- "time": "0.005s",
- "classname": ""
- }
- ]
- },
- {
- "name": "LogicTest",
- "tests": 1,
- "failures": 0,
- "errors": 0,
- "time": "0.005s",
- "testsuite": [
- {
- "name": "NonContradiction",
- "status": "RUN",
- "time": "0.005s",
- "classname": ""
- }
- ]
- }
- ]
-}
-```
-
-IMPORTANT: The exact format of the JSON document is subject to change.
-
-### Controlling How Failures Are Reported
-
-#### Turning Assertion Failures into Break-Points
-
-When running test programs under a debugger, it's very convenient if the
-debugger can catch an assertion failure and automatically drop into interactive
-mode. googletest's *break-on-failure* mode supports this behavior.
-
-To enable it, set the `GTEST_BREAK_ON_FAILURE` environment variable to a value
-other than `0`. Alternatively, you can use the `--gtest_break_on_failure`
-command line flag.
-
-#### Disabling Catching Test-Thrown Exceptions
-
-googletest can be used either with or without exceptions enabled. If a test
-throws a C++ exception or (on Windows) a structured exception (SEH), by default
-googletest catches it, reports it as a test failure, and continues with the next
-test method. This maximizes the coverage of a test run. Also, on Windows an
-uncaught exception will cause a pop-up window, so catching the exceptions allows
-you to run the tests automatically.
-
-When debugging the test failures, however, you may instead want the exceptions
-to be handled by the debugger, such that you can examine the call stack when an
-exception is thrown. To achieve that, set the `GTEST_CATCH_EXCEPTIONS`
-environment variable to `0`, or use the `--gtest_catch_exceptions=0` flag when
-running the tests.
+++ /dev/null
-# Googletest FAQ
-
-<!-- GOOGLETEST_CM0014 DO NOT DELETE -->
-
-## Why should test suite names and test names not contain underscore?
-
-Underscore (`_`) is special, as C++ reserves the following to be used by the
-compiler and the standard library:
-
-1. any identifier that starts with an `_` followed by an upper-case letter, and
-2. any identifier that contains two consecutive underscores (i.e. `__`)
- *anywhere* in its name.
-
-User code is *prohibited* from using such identifiers.
-
-Now let's look at what this means for `TEST` and `TEST_F`.
-
-Currently `TEST(TestSuiteName, TestName)` generates a class named
-`TestSuiteName_TestName_Test`. What happens if `TestSuiteName` or `TestName`
-contains `_`?
-
-1. If `TestSuiteName` starts with an `_` followed by an upper-case letter (say,
- `_Foo`), we end up with `_Foo_TestName_Test`, which is reserved and thus
- invalid.
-2. If `TestSuiteName` ends with an `_` (say, `Foo_`), we get
- `Foo__TestName_Test`, which is invalid.
-3. If `TestName` starts with an `_` (say, `_Bar`), we get
- `TestSuiteName__Bar_Test`, which is invalid.
-4. If `TestName` ends with an `_` (say, `Bar_`), we get
- `TestSuiteName_Bar__Test`, which is invalid.
-
-So clearly `TestSuiteName` and `TestName` cannot start or end with `_`
-(Actually, `TestSuiteName` can start with `_` -- as long as the `_` isn't
-followed by an upper-case letter. But that's getting complicated. So for
-simplicity we just say that it cannot start with `_`.).
-
-It may seem fine for `TestSuiteName` and `TestName` to contain `_` in the
-middle. However, consider this:
-
-```c++
-TEST(Time, Flies_Like_An_Arrow) { ... }
-TEST(Time_Flies, Like_An_Arrow) { ... }
-```
-
-Now, the two `TEST`s will both generate the same class
-(`Time_Flies_Like_An_Arrow_Test`). That's not good.
-
-So for simplicity, we just ask the users to avoid `_` in `TestSuiteName` and
-`TestName`. The rule is more constraining than necessary, but it's simple and
-easy to remember. It also gives googletest some wiggle room in case its
-implementation needs to change in the future.
-
-If you violate the rule, there may not be immediate consequences, but your test
-may (just may) break with a new compiler (or a new version of the compiler you
-are using) or with a new version of googletest. Therefore it's best to follow
-the rule.
-
-## Why does googletest support `EXPECT_EQ(NULL, ptr)` and `ASSERT_EQ(NULL, ptr)` but not `EXPECT_NE(NULL, ptr)` and `ASSERT_NE(NULL, ptr)`?
-
-First of all you can use `EXPECT_NE(nullptr, ptr)` and `ASSERT_NE(nullptr,
-ptr)`. This is the preferred syntax in the style guide because nullptr does not
-have the type problems that NULL does. Which is why NULL does not work.
-
-Due to some peculiarity of C++, it requires some non-trivial template meta
-programming tricks to support using `NULL` as an argument of the `EXPECT_XX()`
-and `ASSERT_XX()` macros. Therefore we only do it where it's most needed
-(otherwise we make the implementation of googletest harder to maintain and more
-error-prone than necessary).
-
-The `EXPECT_EQ()` macro takes the *expected* value as its first argument and the
-*actual* value as the second. It's reasonable that someone wants to write
-`EXPECT_EQ(NULL, some_expression)`, and this indeed was requested several times.
-Therefore we implemented it.
-
-The need for `EXPECT_NE(NULL, ptr)` isn't nearly as strong. When the assertion
-fails, you already know that `ptr` must be `NULL`, so it doesn't add any
-information to print `ptr` in this case. That means `EXPECT_TRUE(ptr != NULL)`
-works just as well.
-
-If we were to support `EXPECT_NE(NULL, ptr)`, for consistency we'll have to
-support `EXPECT_NE(ptr, NULL)` as well, as unlike `EXPECT_EQ`, we don't have a
-convention on the order of the two arguments for `EXPECT_NE`. This means using
-the template meta programming tricks twice in the implementation, making it even
-harder to understand and maintain. We believe the benefit doesn't justify the
-cost.
-
-Finally, with the growth of the gMock matcher library, we are encouraging people
-to use the unified `EXPECT_THAT(value, matcher)` syntax more often in tests. One
-significant advantage of the matcher approach is that matchers can be easily
-combined to form new matchers, while the `EXPECT_NE`, etc, macros cannot be
-easily combined. Therefore we want to invest more in the matchers than in the
-`EXPECT_XX()` macros.
-
-## I need to test that different implementations of an interface satisfy some common requirements. Should I use typed tests or value-parameterized tests?
-
-For testing various implementations of the same interface, either typed tests or
-value-parameterized tests can get it done. It's really up to you the user to
-decide which is more convenient for you, depending on your particular case. Some
-rough guidelines:
-
-* Typed tests can be easier to write if instances of the different
- implementations can be created the same way, modulo the type. For example,
- if all these implementations have a public default constructor (such that
- you can write `new TypeParam`), or if their factory functions have the same
- form (e.g. `CreateInstance<TypeParam>()`).
-* Value-parameterized tests can be easier to write if you need different code
- patterns to create different implementations' instances, e.g. `new Foo` vs
- `new Bar(5)`. To accommodate for the differences, you can write factory
- function wrappers and pass these function pointers to the tests as their
- parameters.
-* When a typed test fails, the default output includes the name of the type,
- which can help you quickly identify which implementation is wrong.
- Value-parameterized tests only show the number of the failed iteration by
- default. You will need to define a function that returns the iteration name
- and pass it as the third parameter to INSTANTIATE_TEST_SUITE_P to have more
- useful output.
-* When using typed tests, you need to make sure you are testing against the
- interface type, not the concrete types (in other words, you want to make
- sure `implicit_cast<MyInterface*>(my_concrete_impl)` works, not just that
- `my_concrete_impl` works). It's less likely to make mistakes in this area
- when using value-parameterized tests.
-
-I hope I didn't confuse you more. :-) If you don't mind, I'd suggest you to give
-both approaches a try. Practice is a much better way to grasp the subtle
-differences between the two tools. Once you have some concrete experience, you
-can much more easily decide which one to use the next time.
-
-## I got some run-time errors about invalid proto descriptors when using `ProtocolMessageEquals`. Help!
-
-**Note:** `ProtocolMessageEquals` and `ProtocolMessageEquiv` are *deprecated*
-now. Please use `EqualsProto`, etc instead.
-
-`ProtocolMessageEquals` and `ProtocolMessageEquiv` were redefined recently and
-are now less tolerant of invalid protocol buffer definitions. In particular, if
-you have a `foo.proto` that doesn't fully qualify the type of a protocol message
-it references (e.g. `message<Bar>` where it should be `message<blah.Bar>`), you
-will now get run-time errors like:
-
-```
-... descriptor.cc:...] Invalid proto descriptor for file "path/to/foo.proto":
-... descriptor.cc:...] blah.MyMessage.my_field: ".Bar" is not defined.
-```
-
-If you see this, your `.proto` file is broken and needs to be fixed by making
-the types fully qualified. The new definition of `ProtocolMessageEquals` and
-`ProtocolMessageEquiv` just happen to reveal your bug.
-
-## My death test modifies some state, but the change seems lost after the death test finishes. Why?
-
-Death tests (`EXPECT_DEATH`, etc) are executed in a sub-process s.t. the
-expected crash won't kill the test program (i.e. the parent process). As a
-result, any in-memory side effects they incur are observable in their respective
-sub-processes, but not in the parent process. You can think of them as running
-in a parallel universe, more or less.
-
-In particular, if you use mocking and the death test statement invokes some mock
-methods, the parent process will think the calls have never occurred. Therefore,
-you may want to move your `EXPECT_CALL` statements inside the `EXPECT_DEATH`
-macro.
-
-## EXPECT_EQ(htonl(blah), blah_blah) generates weird compiler errors in opt mode. Is this a googletest bug?
-
-Actually, the bug is in `htonl()`.
-
-According to `'man htonl'`, `htonl()` is a *function*, which means it's valid to
-use `htonl` as a function pointer. However, in opt mode `htonl()` is defined as
-a *macro*, which breaks this usage.
-
-Worse, the macro definition of `htonl()` uses a `gcc` extension and is *not*
-standard C++. That hacky implementation has some ad hoc limitations. In
-particular, it prevents you from writing `Foo<sizeof(htonl(x))>()`, where `Foo`
-is a template that has an integral argument.
-
-The implementation of `EXPECT_EQ(a, b)` uses `sizeof(... a ...)` inside a
-template argument, and thus doesn't compile in opt mode when `a` contains a call
-to `htonl()`. It is difficult to make `EXPECT_EQ` bypass the `htonl()` bug, as
-the solution must work with different compilers on various platforms.
-
-`htonl()` has some other problems as described in `//util/endian/endian.h`,
-which defines `ghtonl()` to replace it. `ghtonl()` does the same thing `htonl()`
-does, only without its problems. We suggest you to use `ghtonl()` instead of
-`htonl()`, both in your tests and production code.
-
-`//util/endian/endian.h` also defines `ghtons()`, which solves similar problems
-in `htons()`.
-
-Don't forget to add `//util/endian` to the list of dependencies in the `BUILD`
-file wherever `ghtonl()` and `ghtons()` are used. The library consists of a
-single header file and will not bloat your binary.
-
-## The compiler complains about "undefined references" to some static const member variables, but I did define them in the class body. What's wrong?
-
-If your class has a static data member:
-
-```c++
-// foo.h
-class Foo {
- ...
- static const int kBar = 100;
-};
-```
-
-You also need to define it *outside* of the class body in `foo.cc`:
-
-```c++
-const int Foo::kBar; // No initializer here.
-```
-
-Otherwise your code is **invalid C++**, and may break in unexpected ways. In
-particular, using it in googletest comparison assertions (`EXPECT_EQ`, etc) will
-generate an "undefined reference" linker error. The fact that "it used to work"
-doesn't mean it's valid. It just means that you were lucky. :-)
-
-## Can I derive a test fixture from another?
-
-Yes.
-
-Each test fixture has a corresponding and same named test suite. This means only
-one test suite can use a particular fixture. Sometimes, however, multiple test
-cases may want to use the same or slightly different fixtures. For example, you
-may want to make sure that all of a GUI library's test suites don't leak
-important system resources like fonts and brushes.
-
-In googletest, you share a fixture among test suites by putting the shared logic
-in a base test fixture, then deriving from that base a separate fixture for each
-test suite that wants to use this common logic. You then use `TEST_F()` to write
-tests using each derived fixture.
-
-Typically, your code looks like this:
-
-```c++
-// Defines a base test fixture.
-class BaseTest : public ::testing::Test {
- protected:
- ...
-};
-
-// Derives a fixture FooTest from BaseTest.
-class FooTest : public BaseTest {
- protected:
- void SetUp() override {
- BaseTest::SetUp(); // Sets up the base fixture first.
- ... additional set-up work ...
- }
-
- void TearDown() override {
- ... clean-up work for FooTest ...
- BaseTest::TearDown(); // Remember to tear down the base fixture
- // after cleaning up FooTest!
- }
-
- ... functions and variables for FooTest ...
-};
-
-// Tests that use the fixture FooTest.
-TEST_F(FooTest, Bar) { ... }
-TEST_F(FooTest, Baz) { ... }
-
-... additional fixtures derived from BaseTest ...
-```
-
-If necessary, you can continue to derive test fixtures from a derived fixture.
-googletest has no limit on how deep the hierarchy can be.
-
-For a complete example using derived test fixtures, see
-[sample5_unittest.cc](../samples/sample5_unittest.cc).
-
-## My compiler complains "void value not ignored as it ought to be." What does this mean?
-
-You're probably using an `ASSERT_*()` in a function that doesn't return `void`.
-`ASSERT_*()` can only be used in `void` functions, due to exceptions being
-disabled by our build system. Please see more details
-[here](advanced.md#assertion-placement).
-
-## My death test hangs (or seg-faults). How do I fix it?
-
-In googletest, death tests are run in a child process and the way they work is
-delicate. To write death tests you really need to understand how they work.
-Please make sure you have read [this](advanced.md#how-it-works).
-
-In particular, death tests don't like having multiple threads in the parent
-process. So the first thing you can try is to eliminate creating threads outside
-of `EXPECT_DEATH()`. For example, you may want to use mocks or fake objects
-instead of real ones in your tests.
-
-Sometimes this is impossible as some library you must use may be creating
-threads before `main()` is even reached. In this case, you can try to minimize
-the chance of conflicts by either moving as many activities as possible inside
-`EXPECT_DEATH()` (in the extreme case, you want to move everything inside), or
-leaving as few things as possible in it. Also, you can try to set the death test
-style to `"threadsafe"`, which is safer but slower, and see if it helps.
-
-If you go with thread-safe death tests, remember that they rerun the test
-program from the beginning in the child process. Therefore make sure your
-program can run side-by-side with itself and is deterministic.
-
-In the end, this boils down to good concurrent programming. You have to make
-sure that there is no race conditions or dead locks in your program. No silver
-bullet - sorry!
-
-## Should I use the constructor/destructor of the test fixture or SetUp()/TearDown()? {#CtorVsSetUp}
-
-The first thing to remember is that googletest does **not** reuse the same test
-fixture object across multiple tests. For each `TEST_F`, googletest will create
-a **fresh** test fixture object, immediately call `SetUp()`, run the test body,
-call `TearDown()`, and then delete the test fixture object.
-
-When you need to write per-test set-up and tear-down logic, you have the choice
-between using the test fixture constructor/destructor or `SetUp()/TearDown()`.
-The former is usually preferred, as it has the following benefits:
-
-* By initializing a member variable in the constructor, we have the option to
- make it `const`, which helps prevent accidental changes to its value and
- makes the tests more obviously correct.
-* In case we need to subclass the test fixture class, the subclass'
- constructor is guaranteed to call the base class' constructor *first*, and
- the subclass' destructor is guaranteed to call the base class' destructor
- *afterward*. With `SetUp()/TearDown()`, a subclass may make the mistake of
- forgetting to call the base class' `SetUp()/TearDown()` or call them at the
- wrong time.
-
-You may still want to use `SetUp()/TearDown()` in the following cases:
-
-* C++ does not allow virtual function calls in constructors and destructors.
- You can call a method declared as virtual, but it will not use dynamic
- dispatch, it will use the definition from the class the constructor of which
- is currently executing. This is because calling a virtual method before the
- derived class constructor has a chance to run is very dangerous - the
- virtual method might operate on uninitialized data. Therefore, if you need
- to call a method that will be overridden in a derived class, you have to use
- `SetUp()/TearDown()`.
-* In the body of a constructor (or destructor), it's not possible to use the
- `ASSERT_xx` macros. Therefore, if the set-up operation could cause a fatal
- test failure that should prevent the test from running, it's necessary to
- use `abort` <!-- GOOGLETEST_CM0015 DO NOT DELETE --> and abort the whole test executable,
- or to use `SetUp()` instead of a constructor.
-* If the tear-down operation could throw an exception, you must use
- `TearDown()` as opposed to the destructor, as throwing in a destructor leads
- to undefined behavior and usually will kill your program right away. Note
- that many standard libraries (like STL) may throw when exceptions are
- enabled in the compiler. Therefore you should prefer `TearDown()` if you
- want to write portable tests that work with or without exceptions.
-* The googletest team is considering making the assertion macros throw on
- platforms where exceptions are enabled (e.g. Windows, Mac OS, and Linux
- client-side), which will eliminate the need for the user to propagate
- failures from a subroutine to its caller. Therefore, you shouldn't use
- googletest assertions in a destructor if your code could run on such a
- platform.
-
-## The compiler complains "no matching function to call" when I use ASSERT_PRED*. How do I fix it?
-
-If the predicate function you use in `ASSERT_PRED*` or `EXPECT_PRED*` is
-overloaded or a template, the compiler will have trouble figuring out which
-overloaded version it should use. `ASSERT_PRED_FORMAT*` and
-`EXPECT_PRED_FORMAT*` don't have this problem.
-
-If you see this error, you might want to switch to
-`(ASSERT|EXPECT)_PRED_FORMAT*`, which will also give you a better failure
-message. If, however, that is not an option, you can resolve the problem by
-explicitly telling the compiler which version to pick.
-
-For example, suppose you have
-
-```c++
-bool IsPositive(int n) {
- return n > 0;
-}
-
-bool IsPositive(double x) {
- return x > 0;
-}
-```
-
-you will get a compiler error if you write
-
-```c++
-EXPECT_PRED1(IsPositive, 5);
-```
-
-However, this will work:
-
-```c++
-EXPECT_PRED1(static_cast<bool (*)(int)>(IsPositive), 5);
-```
-
-(The stuff inside the angled brackets for the `static_cast` operator is the type
-of the function pointer for the `int`-version of `IsPositive()`.)
-
-As another example, when you have a template function
-
-```c++
-template <typename T>
-bool IsNegative(T x) {
- return x < 0;
-}
-```
-
-you can use it in a predicate assertion like this:
-
-```c++
-ASSERT_PRED1(IsNegative<int>, -5);
-```
-
-Things are more interesting if your template has more than one parameters. The
-following won't compile:
-
-```c++
-ASSERT_PRED2(GreaterThan<int, int>, 5, 0);
-```
-
-as the C++ pre-processor thinks you are giving `ASSERT_PRED2` 4 arguments, which
-is one more than expected. The workaround is to wrap the predicate function in
-parentheses:
-
-```c++
-ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
-```
-
-## My compiler complains about "ignoring return value" when I call RUN_ALL_TESTS(). Why?
-
-Some people had been ignoring the return value of `RUN_ALL_TESTS()`. That is,
-instead of
-
-```c++
- return RUN_ALL_TESTS();
-```
-
-they write
-
-```c++
- RUN_ALL_TESTS();
-```
-
-This is **wrong and dangerous**. The testing services needs to see the return
-value of `RUN_ALL_TESTS()` in order to determine if a test has passed. If your
-`main()` function ignores it, your test will be considered successful even if it
-has a googletest assertion failure. Very bad.
-
-We have decided to fix this (thanks to Michael Chastain for the idea). Now, your
-code will no longer be able to ignore `RUN_ALL_TESTS()` when compiled with
-`gcc`. If you do so, you'll get a compiler error.
-
-If you see the compiler complaining about you ignoring the return value of
-`RUN_ALL_TESTS()`, the fix is simple: just make sure its value is used as the
-return value of `main()`.
-
-But how could we introduce a change that breaks existing tests? Well, in this
-case, the code was already broken in the first place, so we didn't break it. :-)
-
-## My compiler complains that a constructor (or destructor) cannot return a value. What's going on?
-
-Due to a peculiarity of C++, in order to support the syntax for streaming
-messages to an `ASSERT_*`, e.g.
-
-```c++
- ASSERT_EQ(1, Foo()) << "blah blah" << foo;
-```
-
-we had to give up using `ASSERT*` and `FAIL*` (but not `EXPECT*` and
-`ADD_FAILURE*`) in constructors and destructors. The workaround is to move the
-content of your constructor/destructor to a private void member function, or
-switch to `EXPECT_*()` if that works. This
-[section](advanced.md#assertion-placement) in the user's guide explains it.
-
-## My SetUp() function is not called. Why?
-
-C++ is case-sensitive. Did you spell it as `Setup()`?
-
-Similarly, sometimes people spell `SetUpTestSuite()` as `SetupTestSuite()` and
-wonder why it's never called.
-
-
-## I have several test suites which share the same test fixture logic, do I have to define a new test fixture class for each of them? This seems pretty tedious.
-
-You don't have to. Instead of
-
-```c++
-class FooTest : public BaseTest {};
-
-TEST_F(FooTest, Abc) { ... }
-TEST_F(FooTest, Def) { ... }
-
-class BarTest : public BaseTest {};
-
-TEST_F(BarTest, Abc) { ... }
-TEST_F(BarTest, Def) { ... }
-```
-
-you can simply `typedef` the test fixtures:
-
-```c++
-typedef BaseTest FooTest;
-
-TEST_F(FooTest, Abc) { ... }
-TEST_F(FooTest, Def) { ... }
-
-typedef BaseTest BarTest;
-
-TEST_F(BarTest, Abc) { ... }
-TEST_F(BarTest, Def) { ... }
-```
-
-## googletest output is buried in a whole bunch of LOG messages. What do I do?
-
-The googletest output is meant to be a concise and human-friendly report. If
-your test generates textual output itself, it will mix with the googletest
-output, making it hard to read. However, there is an easy solution to this
-problem.
-
-Since `LOG` messages go to stderr, we decided to let googletest output go to
-stdout. This way, you can easily separate the two using redirection. For
-example:
-
-```shell
-$ ./my_test > gtest_output.txt
-```
-
-## Why should I prefer test fixtures over global variables?
-
-There are several good reasons:
-
-1. It's likely your test needs to change the states of its global variables.
- This makes it difficult to keep side effects from escaping one test and
- contaminating others, making debugging difficult. By using fixtures, each
- test has a fresh set of variables that's different (but with the same
- names). Thus, tests are kept independent of each other.
-2. Global variables pollute the global namespace.
-3. Test fixtures can be reused via subclassing, which cannot be done easily
- with global variables. This is useful if many test suites have something in
- common.
-
-## What can the statement argument in ASSERT_DEATH() be?
-
-`ASSERT_DEATH(*statement*, *regex*)` (or any death assertion macro) can be used
-wherever `*statement*` is valid. So basically `*statement*` can be any C++
-statement that makes sense in the current context. In particular, it can
-reference global and/or local variables, and can be:
-
-* a simple function call (often the case),
-* a complex expression, or
-* a compound statement.
-
-Some examples are shown here:
-
-```c++
-// A death test can be a simple function call.
-TEST(MyDeathTest, FunctionCall) {
- ASSERT_DEATH(Xyz(5), "Xyz failed");
-}
-
-// Or a complex expression that references variables and functions.
-TEST(MyDeathTest, ComplexExpression) {
- const bool c = Condition();
- ASSERT_DEATH((c ? Func1(0) : object2.Method("test")),
- "(Func1|Method) failed");
-}
-
-// Death assertions can be used any where in a function. In
-// particular, they can be inside a loop.
-TEST(MyDeathTest, InsideLoop) {
- // Verifies that Foo(0), Foo(1), ..., and Foo(4) all die.
- for (int i = 0; i < 5; i++) {
- EXPECT_DEATH_M(Foo(i), "Foo has \\d+ errors",
- ::testing::Message() << "where i is " << i);
- }
-}
-
-// A death assertion can contain a compound statement.
-TEST(MyDeathTest, CompoundStatement) {
- // Verifies that at lease one of Bar(0), Bar(1), ..., and
- // Bar(4) dies.
- ASSERT_DEATH({
- for (int i = 0; i < 5; i++) {
- Bar(i);
- }
- },
- "Bar has \\d+ errors");
-}
-```
-
-gtest-death-test_test.cc contains more examples if you are interested.
-
-## I have a fixture class `FooTest`, but `TEST_F(FooTest, Bar)` gives me error ``"no matching function for call to `FooTest::FooTest()'"``. Why?
-
-Googletest needs to be able to create objects of your test fixture class, so it
-must have a default constructor. Normally the compiler will define one for you.
-However, there are cases where you have to define your own:
-
-* If you explicitly declare a non-default constructor for class `FooTest`
- (`DISALLOW_EVIL_CONSTRUCTORS()` does this), then you need to define a
- default constructor, even if it would be empty.
-* If `FooTest` has a const non-static data member, then you have to define the
- default constructor *and* initialize the const member in the initializer
- list of the constructor. (Early versions of `gcc` doesn't force you to
- initialize the const member. It's a bug that has been fixed in `gcc 4`.)
-
-## Why does ASSERT_DEATH complain about previous threads that were already joined?
-
-With the Linux pthread library, there is no turning back once you cross the line
-from single thread to multiple threads. The first time you create a thread, a
-manager thread is created in addition, so you get 3, not 2, threads. Later when
-the thread you create joins the main thread, the thread count decrements by 1,
-but the manager thread will never be killed, so you still have 2 threads, which
-means you cannot safely run a death test.
-
-The new NPTL thread library doesn't suffer from this problem, as it doesn't
-create a manager thread. However, if you don't control which machine your test
-runs on, you shouldn't depend on this.
-
-## Why does googletest require the entire test suite, instead of individual tests, to be named *DeathTest when it uses ASSERT_DEATH?
-
-googletest does not interleave tests from different test suites. That is, it
-runs all tests in one test suite first, and then runs all tests in the next test
-suite, and so on. googletest does this because it needs to set up a test suite
-before the first test in it is run, and tear it down afterwords. Splitting up
-the test case would require multiple set-up and tear-down processes, which is
-inefficient and makes the semantics unclean.
-
-If we were to determine the order of tests based on test name instead of test
-case name, then we would have a problem with the following situation:
-
-```c++
-TEST_F(FooTest, AbcDeathTest) { ... }
-TEST_F(FooTest, Uvw) { ... }
-
-TEST_F(BarTest, DefDeathTest) { ... }
-TEST_F(BarTest, Xyz) { ... }
-```
-
-Since `FooTest.AbcDeathTest` needs to run before `BarTest.Xyz`, and we don't
-interleave tests from different test suites, we need to run all tests in the
-`FooTest` case before running any test in the `BarTest` case. This contradicts
-with the requirement to run `BarTest.DefDeathTest` before `FooTest.Uvw`.
-
-## But I don't like calling my entire test suite \*DeathTest when it contains both death tests and non-death tests. What do I do?
-
-You don't have to, but if you like, you may split up the test suite into
-`FooTest` and `FooDeathTest`, where the names make it clear that they are
-related:
-
-```c++
-class FooTest : public ::testing::Test { ... };
-
-TEST_F(FooTest, Abc) { ... }
-TEST_F(FooTest, Def) { ... }
-
-using FooDeathTest = FooTest;
-
-TEST_F(FooDeathTest, Uvw) { ... EXPECT_DEATH(...) ... }
-TEST_F(FooDeathTest, Xyz) { ... ASSERT_DEATH(...) ... }
-```
-
-## googletest prints the LOG messages in a death test's child process only when the test fails. How can I see the LOG messages when the death test succeeds?
-
-Printing the LOG messages generated by the statement inside `EXPECT_DEATH()`
-makes it harder to search for real problems in the parent's log. Therefore,
-googletest only prints them when the death test has failed.
-
-If you really need to see such LOG messages, a workaround is to temporarily
-break the death test (e.g. by changing the regex pattern it is expected to
-match). Admittedly, this is a hack. We'll consider a more permanent solution
-after the fork-and-exec-style death tests are implemented.
-
-## The compiler complains about "no match for 'operator<<'" when I use an assertion. What gives?
-
-If you use a user-defined type `FooType` in an assertion, you must make sure
-there is an `std::ostream& operator<<(std::ostream&, const FooType&)` function
-defined such that we can print a value of `FooType`.
-
-In addition, if `FooType` is declared in a name space, the `<<` operator also
-needs to be defined in the *same* name space. See https://abseil.io/tips/49 for details.
-
-## How do I suppress the memory leak messages on Windows?
-
-Since the statically initialized googletest singleton requires allocations on
-the heap, the Visual C++ memory leak detector will report memory leaks at the
-end of the program run. The easiest way to avoid this is to use the
-`_CrtMemCheckpoint` and `_CrtMemDumpAllObjectsSince` calls to not report any
-statically initialized heap objects. See MSDN for more details and additional
-heap check/debug routines.
-
-## How can my code detect if it is running in a test?
-
-If you write code that sniffs whether it's running in a test and does different
-things accordingly, you are leaking test-only logic into production code and
-there is no easy way to ensure that the test-only code paths aren't run by
-mistake in production. Such cleverness also leads to
-[Heisenbugs](https://en.wikipedia.org/wiki/Heisenbug). Therefore we strongly
-advise against the practice, and googletest doesn't provide a way to do it.
-
-In general, the recommended way to cause the code to behave differently under
-test is [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). You can inject
-different functionality from the test and from the production code. Since your
-production code doesn't link in the for-test logic at all (the
-[`testonly`](https://docs.bazel.build/versions/master/be/common-definitions.html#common.testonly) attribute for BUILD targets helps to ensure
-that), there is no danger in accidentally running it.
-
-However, if you *really*, *really*, *really* have no choice, and if you follow
-the rule of ending your test program names with `_test`, you can use the
-*horrible* hack of sniffing your executable name (`argv[0]` in `main()`) to know
-whether the code is under test.
-
-## How do I temporarily disable a test?
-
-If you have a broken test that you cannot fix right away, you can add the
-DISABLED_ prefix to its name. This will exclude it from execution. This is
-better than commenting out the code or using #if 0, as disabled tests are still
-compiled (and thus won't rot).
-
-To include disabled tests in test execution, just invoke the test program with
-the --gtest_also_run_disabled_tests flag.
-
-## Is it OK if I have two separate `TEST(Foo, Bar)` test methods defined in different namespaces?
-
-Yes.
-
-The rule is **all test methods in the same test suite must use the same fixture
-class.** This means that the following is **allowed** because both tests use the
-same fixture class (`::testing::Test`).
-
-```c++
-namespace foo {
-TEST(CoolTest, DoSomething) {
- SUCCEED();
-}
-} // namespace foo
-
-namespace bar {
-TEST(CoolTest, DoSomething) {
- SUCCEED();
-}
-} // namespace bar
-```
-
-However, the following code is **not allowed** and will produce a runtime error
-from googletest because the test methods are using different test fixture
-classes with the same test suite name.
-
-```c++
-namespace foo {
-class CoolTest : public ::testing::Test {}; // Fixture foo::CoolTest
-TEST_F(CoolTest, DoSomething) {
- SUCCEED();
-}
-} // namespace foo
-
-namespace bar {
-class CoolTest : public ::testing::Test {}; // Fixture: bar::CoolTest
-TEST_F(CoolTest, DoSomething) {
- SUCCEED();
-}
-} // namespace bar
-```
+++ /dev/null
-## Using GoogleTest from various build systems
-
-GoogleTest comes with pkg-config files that can be used to determine all
-necessary flags for compiling and linking to GoogleTest (and GoogleMock).
-Pkg-config is a standardised plain-text format containing
-
-* the includedir (-I) path
-* necessary macro (-D) definitions
-* further required flags (-pthread)
-* the library (-L) path
-* the library (-l) to link to
-
-All current build systems support pkg-config in one way or another. For all
-examples here we assume you want to compile the sample
-`samples/sample3_unittest.cc`.
-
-### CMake
-
-Using `pkg-config` in CMake is fairly easy:
-
-```cmake
-cmake_minimum_required(VERSION 3.0)
-
-cmake_policy(SET CMP0048 NEW)
-project(my_gtest_pkgconfig VERSION 0.0.1 LANGUAGES CXX)
-
-find_package(PkgConfig)
-pkg_search_module(GTEST REQUIRED gtest_main)
-
-add_executable(testapp samples/sample3_unittest.cc)
-target_link_libraries(testapp ${GTEST_LDFLAGS})
-target_compile_options(testapp PUBLIC ${GTEST_CFLAGS})
-
-include(CTest)
-add_test(first_and_only_test testapp)
-```
-
-It is generally recommended that you use `target_compile_options` + `_CFLAGS`
-over `target_include_directories` + `_INCLUDE_DIRS` as the former includes not
-just -I flags (GoogleTest might require a macro indicating to internal headers
-that all libraries have been compiled with threading enabled. In addition,
-GoogleTest might also require `-pthread` in the compiling step, and as such
-splitting the pkg-config `Cflags` variable into include dirs and macros for
-`target_compile_definitions()` might still miss this). The same recommendation
-goes for using `_LDFLAGS` over the more commonplace `_LIBRARIES`, which happens
-to discard `-L` flags and `-pthread`.
-
-### Autotools
-
-Finding GoogleTest in Autoconf and using it from Automake is also fairly easy:
-
-In your `configure.ac`:
-
-```
-AC_PREREQ([2.69])
-AC_INIT([my_gtest_pkgconfig], [0.0.1])
-AC_CONFIG_SRCDIR([samples/sample3_unittest.cc])
-AC_PROG_CXX
-
-PKG_CHECK_MODULES([GTEST], [gtest_main])
-
-AM_INIT_AUTOMAKE([foreign subdir-objects])
-AC_CONFIG_FILES([Makefile])
-AC_OUTPUT
-```
-
-and in your `Makefile.am`:
-
-```
-check_PROGRAMS = testapp
-TESTS = $(check_PROGRAMS)
-
-testapp_SOURCES = samples/sample3_unittest.cc
-testapp_CXXFLAGS = $(GTEST_CFLAGS)
-testapp_LDADD = $(GTEST_LIBS)
-```
-
-### Meson
-
-Meson natively uses pkgconfig to query dependencies:
-
-```
-project('my_gtest_pkgconfig', 'cpp', version : '0.0.1')
-
-gtest_dep = dependency('gtest_main')
-
-testapp = executable(
- 'testapp',
- files(['samples/sample3_unittest.cc']),
- dependencies : gtest_dep,
- install : false)
-
-test('first_and_only_test', testapp)
-```
-
-### Plain Makefiles
-
-Since `pkg-config` is a small Unix command-line utility, it can be used in
-handwritten `Makefile`s too:
-
-```makefile
-GTEST_CFLAGS = `pkg-config --cflags gtest_main`
-GTEST_LIBS = `pkg-config --libs gtest_main`
-
-.PHONY: tests all
-
-tests: all
- ./testapp
-
-all: testapp
-
-testapp: testapp.o
- $(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@ $(GTEST_LIBS)
-
-testapp.o: samples/sample3_unittest.cc
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) $< -c -o $@ $(GTEST_CFLAGS)
-```
-
-### Help! pkg-config can't find GoogleTest!
-
-Let's say you have a `CMakeLists.txt` along the lines of the one in this
-tutorial and you try to run `cmake`. It is very possible that you get a failure
-along the lines of:
-
-```
--- Checking for one of the modules 'gtest_main'
-CMake Error at /usr/share/cmake/Modules/FindPkgConfig.cmake:640 (message):
- None of the required 'gtest_main' found
-```
-
-These failures are common if you installed GoogleTest yourself and have not
-sourced it from a distro or other package manager. If so, you need to tell
-pkg-config where it can find the `.pc` files containing the information. Say you
-installed GoogleTest to `/usr/local`, then it might be that the `.pc` files are
-installed under `/usr/local/lib64/pkgconfig`. If you set
-
-```
-export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig
-```
-
-pkg-config will also try to look in `PKG_CONFIG_PATH` to find `gtest_main.pc`.
+++ /dev/null
-# Googletest Primer
-
-## Introduction: Why googletest?
-
-*googletest* helps you write better C++ tests.
-
-googletest is a testing framework developed by the Testing Technology team with
-Google's specific requirements and constraints in mind. Whether you work on
-Linux, Windows, or a Mac, if you write C++ code, googletest can help you. And it
-supports *any* kind of tests, not just unit tests.
-
-So what makes a good test, and how does googletest fit in? We believe:
-
-1. Tests should be *independent* and *repeatable*. It's a pain to debug a test
- that succeeds or fails as a result of other tests. googletest isolates the
- tests by running each of them on a different object. When a test fails,
- googletest allows you to run it in isolation for quick debugging.
-2. Tests should be well *organized* and reflect the structure of the tested
- code. googletest groups related tests into test suites that can share data
- and subroutines. This common pattern is easy to recognize and makes tests
- easy to maintain. Such consistency is especially helpful when people switch
- projects and start to work on a new code base.
-3. Tests should be *portable* and *reusable*. Google has a lot of code that is
- platform-neutral; its tests should also be platform-neutral. googletest
- works on different OSes, with different compilers, with or without
- exceptions, so googletest tests can work with a variety of configurations.
-4. When tests fail, they should provide as much *information* about the problem
- as possible. googletest doesn't stop at the first test failure. Instead, it
- only stops the current test and continues with the next. You can also set up
- tests that report non-fatal failures after which the current test continues.
- Thus, you can detect and fix multiple bugs in a single run-edit-compile
- cycle.
-5. The testing framework should liberate test writers from housekeeping chores
- and let them focus on the test *content*. googletest automatically keeps
- track of all tests defined, and doesn't require the user to enumerate them
- in order to run them.
-6. Tests should be *fast*. With googletest, you can reuse shared resources
- across tests and pay for the set-up/tear-down only once, without making
- tests depend on each other.
-
-Since googletest is based on the popular xUnit architecture, you'll feel right
-at home if you've used JUnit or PyUnit before. If not, it will take you about 10
-minutes to learn the basics and get started. So let's go!
-
-## Beware of the nomenclature
-
-_Note:_ There might be some confusion arising from different definitions of the
-terms _Test_, _Test Case_ and _Test Suite_, so beware of misunderstanding these.
-
-Historically, googletest started to use the term _Test Case_ for grouping
-related tests, whereas current publications, including International Software
-Testing Qualifications Board ([ISTQB](http://www.istqb.org/)) materials and
-various textbooks on software quality, use the term
-_[Test Suite][istqb test suite]_ for this.
-
-The related term _Test_, as it is used in googletest, corresponds to the term
-_[Test Case][istqb test case]_ of ISTQB and others.
-
-The term _Test_ is commonly of broad enough sense, including ISTQB's definition
-of _Test Case_, so it's not much of a problem here. But the term _Test Case_ as
-was used in Google Test is of contradictory sense and thus confusing.
-
-googletest recently started replacing the term _Test Case_ with _Test Suite_.
-The preferred API is *TestSuite*. The older TestCase API is being slowly
-deprecated and refactored away.
-
-So please be aware of the different definitions of the terms:
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-Meaning | googletest Term | [ISTQB](http://www.istqb.org/) Term
-:----------------------------------------------------------------------------------- | :---------------------- | :----------------------------------
-Exercise a particular program path with specific input values and verify the results | [TEST()](#simple-tests) | [Test Case][istqb test case]
-
-<!-- mdformat on -->
-
-[istqb test case]: http://glossary.istqb.org/en/search/test%20case
-[istqb test suite]: http://glossary.istqb.org/en/search/test%20suite
-
-## Basic Concepts
-
-When using googletest, you start by writing *assertions*, which are statements
-that check whether a condition is true. An assertion's result can be *success*,
-*nonfatal failure*, or *fatal failure*. If a fatal failure occurs, it aborts the
-current function; otherwise the program continues normally.
-
-*Tests* use assertions to verify the tested code's behavior. If a test crashes
-or has a failed assertion, then it *fails*; otherwise it *succeeds*.
-
-A *test suite* contains one or many tests. You should group your tests into test
-suites that reflect the structure of the tested code. When multiple tests in a
-test suite need to share common objects and subroutines, you can put them into a
-*test fixture* class.
-
-A *test program* can contain multiple test suites.
-
-We'll now explain how to write a test program, starting at the individual
-assertion level and building up to tests and test suites.
-
-## Assertions
-
-googletest assertions are macros that resemble function calls. You test a class
-or function by making assertions about its behavior. When an assertion fails,
-googletest prints the assertion's source file and line number location, along
-with a failure message. You may also supply a custom failure message which will
-be appended to googletest's message.
-
-The assertions come in pairs that test the same thing but have different effects
-on the current function. `ASSERT_*` versions generate fatal failures when they
-fail, and **abort the current function**. `EXPECT_*` versions generate nonfatal
-failures, which don't abort the current function. Usually `EXPECT_*` are
-preferred, as they allow more than one failure to be reported in a test.
-However, you should use `ASSERT_*` if it doesn't make sense to continue when the
-assertion in question fails.
-
-Since a failed `ASSERT_*` returns from the current function immediately,
-possibly skipping clean-up code that comes after it, it may cause a space leak.
-Depending on the nature of the leak, it may or may not be worth fixing - so keep
-this in mind if you get a heap checker error in addition to assertion errors.
-
-To provide a custom failure message, simply stream it into the macro using the
-`<<` operator or a sequence of such operators. An example:
-
-```c++
-ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";
-
-for (int i = 0; i < x.size(); ++i) {
- EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
-}
-```
-
-Anything that can be streamed to an `ostream` can be streamed to an assertion
-macro--in particular, C strings and `string` objects. If a wide string
-(`wchar_t*`, `TCHAR*` in `UNICODE` mode on Windows, or `std::wstring`) is
-streamed to an assertion, it will be translated to UTF-8 when printed.
-
-### Basic Assertions
-
-These assertions do basic true/false condition testing.
-
-Fatal assertion | Nonfatal assertion | Verifies
--------------------------- | -------------------------- | --------------------
-`ASSERT_TRUE(condition);` | `EXPECT_TRUE(condition);` | `condition` is true
-`ASSERT_FALSE(condition);` | `EXPECT_FALSE(condition);` | `condition` is false
-
-Remember, when they fail, `ASSERT_*` yields a fatal failure and returns from the
-current function, while `EXPECT_*` yields a nonfatal failure, allowing the
-function to continue running. In either case, an assertion failure means its
-containing test fails.
-
-**Availability**: Linux, Windows, Mac.
-
-### Binary Comparison
-
-This section describes assertions that compare two values.
-
-Fatal assertion | Nonfatal assertion | Verifies
------------------------- | ------------------------ | --------------
-`ASSERT_EQ(val1, val2);` | `EXPECT_EQ(val1, val2);` | `val1 == val2`
-`ASSERT_NE(val1, val2);` | `EXPECT_NE(val1, val2);` | `val1 != val2`
-`ASSERT_LT(val1, val2);` | `EXPECT_LT(val1, val2);` | `val1 < val2`
-`ASSERT_LE(val1, val2);` | `EXPECT_LE(val1, val2);` | `val1 <= val2`
-`ASSERT_GT(val1, val2);` | `EXPECT_GT(val1, val2);` | `val1 > val2`
-`ASSERT_GE(val1, val2);` | `EXPECT_GE(val1, val2);` | `val1 >= val2`
-
-Value arguments must be comparable by the assertion's comparison operator or
-you'll get a compiler error. We used to require the arguments to support the
-`<<` operator for streaming to an `ostream`, but this is no longer necessary. If
-`<<` is supported, it will be called to print the arguments when the assertion
-fails; otherwise googletest will attempt to print them in the best way it can.
-For more details and how to customize the printing of the arguments, see the
-[documentation](../../googlemock/docs/cook_book.md#teaching-gmock-how-to-print-your-values).
-
-These assertions can work with a user-defined type, but only if you define the
-corresponding comparison operator (e.g., `==` or `<`). Since this is discouraged
-by the Google
-[C++ Style Guide](https://google.github.io/styleguide/cppguide.html#Operator_Overloading),
-you may need to use `ASSERT_TRUE()` or `EXPECT_TRUE()` to assert the equality of
-two objects of a user-defined type.
-
-However, when possible, `ASSERT_EQ(actual, expected)` is preferred to
-`ASSERT_TRUE(actual == expected)`, since it tells you `actual` and `expected`'s
-values on failure.
-
-Arguments are always evaluated exactly once. Therefore, it's OK for the
-arguments to have side effects. However, as with any ordinary C/C++ function,
-the arguments' evaluation order is undefined (i.e., the compiler is free to
-choose any order), and your code should not depend on any particular argument
-evaluation order.
-
-`ASSERT_EQ()` does pointer equality on pointers. If used on two C strings, it
-tests if they are in the same memory location, not if they have the same value.
-Therefore, if you want to compare C strings (e.g. `const char*`) by value, use
-`ASSERT_STREQ()`, which will be described later on. In particular, to assert
-that a C string is `NULL`, use `ASSERT_STREQ(c_string, NULL)`. Consider using
-`ASSERT_EQ(c_string, nullptr)` if c++11 is supported. To compare two `string`
-objects, you should use `ASSERT_EQ`.
-
-When doing pointer comparisons use `*_EQ(ptr, nullptr)` and `*_NE(ptr, nullptr)`
-instead of `*_EQ(ptr, NULL)` and `*_NE(ptr, NULL)`. This is because `nullptr` is
-typed, while `NULL` is not. See the [FAQ](faq.md) for more details.
-
-If you're working with floating point numbers, you may want to use the floating
-point variations of some of these macros in order to avoid problems caused by
-rounding. See [Advanced googletest Topics](advanced.md) for details.
-
-Macros in this section work with both narrow and wide string objects (`string`
-and `wstring`).
-
-**Availability**: Linux, Windows, Mac.
-
-**Historical note**: Before February 2016 `*_EQ` had a convention of calling it
-as `ASSERT_EQ(expected, actual)`, so lots of existing code uses this order. Now
-`*_EQ` treats both parameters in the same way.
-
-### String Comparison
-
-The assertions in this group compare two **C strings**. If you want to compare
-two `string` objects, use `EXPECT_EQ`, `EXPECT_NE`, and etc instead.
-
-<!-- mdformat off(github rendering does not support multiline tables) -->
-
-| Fatal assertion | Nonfatal assertion | Verifies |
-| -------------------------- | ------------------------------ | -------------------------------------------------------- |
-| `ASSERT_STREQ(str1,str2);` | `EXPECT_STREQ(str1,str2);` | the two C strings have the same content |
-| `ASSERT_STRNE(str1,str2);` | `EXPECT_STRNE(str1,str2);` | the two C strings have different contents |
-| `ASSERT_STRCASEEQ(str1,str2);` | `EXPECT_STRCASEEQ(str1,str2);` | the two C strings have the same content, ignoring case |
-| `ASSERT_STRCASENE(str1,str2);` | `EXPECT_STRCASENE(str1,str2);` | the two C strings have different contents, ignoring case |
-
-<!-- mdformat on-->
-
-Note that "CASE" in an assertion name means that case is ignored. A `NULL`
-pointer and an empty string are considered *different*.
-
-`*STREQ*` and `*STRNE*` also accept wide C strings (`wchar_t*`). If a comparison
-of two wide strings fails, their values will be printed as UTF-8 narrow strings.
-
-**Availability**: Linux, Windows, Mac.
-
-**See also**: For more string comparison tricks (substring, prefix, suffix, and
-regular expression matching, for example), see [this](advanced.md) in the
-Advanced googletest Guide.
-
-## Simple Tests
-
-To create a test:
-
-1. Use the `TEST()` macro to define and name a test function. These are
- ordinary C++ functions that don't return a value.
-2. In this function, along with any valid C++ statements you want to include,
- use the various googletest assertions to check values.
-3. The test's result is determined by the assertions; if any assertion in the
- test fails (either fatally or non-fatally), or if the test crashes, the
- entire test fails. Otherwise, it succeeds.
-
-```c++
-TEST(TestSuiteName, TestName) {
- ... test body ...
-}
-```
-
-`TEST()` arguments go from general to specific. The *first* argument is the name
-of the test suite, and the *second* argument is the test's name within the test
-case. Both names must be valid C++ identifiers, and they should not contain
-any underscores (`_`). A test's *full name* consists of its containing test suite and
-its individual name. Tests from different test suites can have the same
-individual name.
-
-For example, let's take a simple integer function:
-
-```c++
-int Factorial(int n); // Returns the factorial of n
-```
-
-A test suite for this function might look like:
-
-```c++
-// Tests factorial of 0.
-TEST(FactorialTest, HandlesZeroInput) {
- EXPECT_EQ(Factorial(0), 1);
-}
-
-// Tests factorial of positive numbers.
-TEST(FactorialTest, HandlesPositiveInput) {
- EXPECT_EQ(Factorial(1), 1);
- EXPECT_EQ(Factorial(2), 2);
- EXPECT_EQ(Factorial(3), 6);
- EXPECT_EQ(Factorial(8), 40320);
-}
-```
-
-googletest groups the test results by test suites, so logically related tests
-should be in the same test suite; in other words, the first argument to their
-`TEST()` should be the same. In the above example, we have two tests,
-`HandlesZeroInput` and `HandlesPositiveInput`, that belong to the same test
-suite `FactorialTest`.
-
-When naming your test suites and tests, you should follow the same convention as
-for
-[naming functions and classes](https://google.github.io/styleguide/cppguide.html#Function_Names).
-
-**Availability**: Linux, Windows, Mac.
-
-## Test Fixtures: Using the Same Data Configuration for Multiple Tests {#same-data-multiple-tests}
-
-If you find yourself writing two or more tests that operate on similar data, you
-can use a *test fixture*. This allows you to reuse the same configuration of
-objects for several different tests.
-
-To create a fixture:
-
-1. Derive a class from `::testing::Test` . Start its body with `protected:`, as
- we'll want to access fixture members from sub-classes.
-2. Inside the class, declare any objects you plan to use.
-3. If necessary, write a default constructor or `SetUp()` function to prepare
- the objects for each test. A common mistake is to spell `SetUp()` as
- **`Setup()`** with a small `u` - Use `override` in C++11 to make sure you
- spelled it correctly.
-4. If necessary, write a destructor or `TearDown()` function to release any
- resources you allocated in `SetUp()` . To learn when you should use the
- constructor/destructor and when you should use `SetUp()/TearDown()`, read
- the [FAQ](faq.md#CtorVsSetUp).
-5. If needed, define subroutines for your tests to share.
-
-When using a fixture, use `TEST_F()` instead of `TEST()` as it allows you to
-access objects and subroutines in the test fixture:
-
-```c++
-TEST_F(TestFixtureName, TestName) {
- ... test body ...
-}
-```
-
-Like `TEST()`, the first argument is the test suite name, but for `TEST_F()`
-this must be the name of the test fixture class. You've probably guessed: `_F`
-is for fixture.
-
-Unfortunately, the C++ macro system does not allow us to create a single macro
-that can handle both types of tests. Using the wrong macro causes a compiler
-error.
-
-Also, you must first define a test fixture class before using it in a
-`TEST_F()`, or you'll get the compiler error "`virtual outside class
-declaration`".
-
-For each test defined with `TEST_F()`, googletest will create a *fresh* test
-fixture at runtime, immediately initialize it via `SetUp()`, run the test,
-clean up by calling `TearDown()`, and then delete the test fixture. Note that
-different tests in the same test suite have different test fixture objects, and
-googletest always deletes a test fixture before it creates the next one.
-googletest does **not** reuse the same test fixture for multiple tests. Any
-changes one test makes to the fixture do not affect other tests.
-
-As an example, let's write tests for a FIFO queue class named `Queue`, which has
-the following interface:
-
-```c++
-template <typename E> // E is the element type.
-class Queue {
- public:
- Queue();
- void Enqueue(const E& element);
- E* Dequeue(); // Returns NULL if the queue is empty.
- size_t size() const;
- ...
-};
-```
-
-First, define a fixture class. By convention, you should give it the name
-`FooTest` where `Foo` is the class being tested.
-
-```c++
-class QueueTest : public ::testing::Test {
- protected:
- void SetUp() override {
- q1_.Enqueue(1);
- q2_.Enqueue(2);
- q2_.Enqueue(3);
- }
-
- // void TearDown() override {}
-
- Queue<int> q0_;
- Queue<int> q1_;
- Queue<int> q2_;
-};
-```
-
-In this case, `TearDown()` is not needed since we don't have to clean up after
-each test, other than what's already done by the destructor.
-
-Now we'll write tests using `TEST_F()` and this fixture.
-
-```c++
-TEST_F(QueueTest, IsEmptyInitially) {
- EXPECT_EQ(q0_.size(), 0);
-}
-
-TEST_F(QueueTest, DequeueWorks) {
- int* n = q0_.Dequeue();
- EXPECT_EQ(n, nullptr);
-
- n = q1_.Dequeue();
- ASSERT_NE(n, nullptr);
- EXPECT_EQ(*n, 1);
- EXPECT_EQ(q1_.size(), 0);
- delete n;
-
- n = q2_.Dequeue();
- ASSERT_NE(n, nullptr);
- EXPECT_EQ(*n, 2);
- EXPECT_EQ(q2_.size(), 1);
- delete n;
-}
-```
-
-The above uses both `ASSERT_*` and `EXPECT_*` assertions. The rule of thumb is
-to use `EXPECT_*` when you want the test to continue to reveal more errors after
-the assertion failure, and use `ASSERT_*` when continuing after failure doesn't
-make sense. For example, the second assertion in the `Dequeue` test is
-`ASSERT_NE(nullptr, n)`, as we need to dereference the pointer `n` later, which
-would lead to a segfault when `n` is `NULL`.
-
-When these tests run, the following happens:
-
-1. googletest constructs a `QueueTest` object (let's call it `t1`).
-2. `t1.SetUp()` initializes `t1`.
-3. The first test (`IsEmptyInitially`) runs on `t1`.
-4. `t1.TearDown()` cleans up after the test finishes.
-5. `t1` is destructed.
-6. The above steps are repeated on another `QueueTest` object, this time
- running the `DequeueWorks` test.
-
-**Availability**: Linux, Windows, Mac.
-
-## Invoking the Tests
-
-`TEST()` and `TEST_F()` implicitly register their tests with googletest. So,
-unlike with many other C++ testing frameworks, you don't have to re-list all
-your defined tests in order to run them.
-
-After defining your tests, you can run them with `RUN_ALL_TESTS()`, which
-returns `0` if all the tests are successful, or `1` otherwise. Note that
-`RUN_ALL_TESTS()` runs *all tests* in your link unit--they can be from
-different test suites, or even different source files.
-
-When invoked, the `RUN_ALL_TESTS()` macro:
-
-* Saves the state of all googletest flags.
-
-* Creates a test fixture object for the first test.
-
-* Initializes it via `SetUp()`.
-
-* Runs the test on the fixture object.
-
-* Cleans up the fixture via `TearDown()`.
-
-* Deletes the fixture.
-
-* Restores the state of all googletest flags.
-
-* Repeats the above steps for the next test, until all tests have run.
-
-If a fatal failure happens the subsequent steps will be skipped.
-
-> IMPORTANT: You must **not** ignore the return value of `RUN_ALL_TESTS()`, or
-> you will get a compiler error. The rationale for this design is that the
-> automated testing service determines whether a test has passed based on its
-> exit code, not on its stdout/stderr output; thus your `main()` function must
-> return the value of `RUN_ALL_TESTS()`.
->
-> Also, you should call `RUN_ALL_TESTS()` only **once**. Calling it more than
-> once conflicts with some advanced googletest features (e.g., thread-safe
-> [death tests](advanced.md#death-tests)) and thus is not supported.
-
-**Availability**: Linux, Windows, Mac.
-
-## Writing the main() Function
-
-Write your own main() function, which should return the value of
-`RUN_ALL_TESTS()`.
-
-You can start from this boilerplate:
-
-```c++
-#include "this/package/foo.h"
-#include "gtest/gtest.h"
-
-namespace {
-
-// The fixture for testing class Foo.
-class FooTest : public ::testing::Test {
- protected:
- // You can remove any or all of the following functions if its body
- // is empty.
-
- FooTest() {
- // You can do set-up work for each test here.
- }
-
- ~FooTest() override {
- // You can do clean-up work that doesn't throw exceptions here.
- }
-
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
-
- void SetUp() override {
- // Code here will be called immediately after the constructor (right
- // before each test).
- }
-
- void TearDown() override {
- // Code here will be called immediately after each test (right
- // before the destructor).
- }
-
- // Objects declared here can be used by all tests in the test suite for Foo.
-};
-
-// Tests that the Foo::Bar() method does Abc.
-TEST_F(FooTest, MethodBarDoesAbc) {
- const std::string input_filepath = "this/package/testdata/myinputfile.dat";
- const std::string output_filepath = "this/package/testdata/myoutputfile.dat";
- Foo f;
- EXPECT_EQ(f.Bar(input_filepath, output_filepath), 0);
-}
-
-// Tests that Foo does Xyz.
-TEST_F(FooTest, DoesXyz) {
- // Exercises the Xyz feature of Foo.
-}
-
-} // namespace
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-```
-
-The `::testing::InitGoogleTest()` function parses the command line for
-googletest flags, and removes all recognized flags. This allows the user to
-control a test program's behavior via various flags, which we'll cover in
-the [AdvancedGuide](advanced.md). You **must** call this function before calling
-`RUN_ALL_TESTS()`, or the flags won't be properly initialized.
-
-On Windows, `InitGoogleTest()` also works with wide strings, so it can be used
-in programs compiled in `UNICODE` mode as well.
-
-But maybe you think that writing all those main() functions is too much work? We
-agree with you completely, and that's why Google Test provides a basic
-implementation of main(). If it fits your needs, then just link your test with
-gtest\_main library and you are good to go.
-
-NOTE: `ParseGUnitFlags()` is deprecated in favor of `InitGoogleTest()`.
-
-## Known Limitations
-
-* Google Test is designed to be thread-safe. The implementation is thread-safe
- on systems where the `pthreads` library is available. It is currently
- _unsafe_ to use Google Test assertions from two threads concurrently on
- other systems (e.g. Windows). In most tests this is not an issue as usually
- the assertions are done in the main thread. If you want to help, you can
- volunteer to implement the necessary synchronization primitives in
- `gtest-port.h` for your platform.
+++ /dev/null
-<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
-
-# The Problem
-
-Template and macro libraries often need to define many classes, functions, or
-macros that vary only (or almost only) in the number of arguments they take.
-It's a lot of repetitive, mechanical, and error-prone work.
-
-Variadic templates and variadic macros can alleviate the problem. However, while
-both are being considered by the C++ committee, neither is in the standard yet
-or widely supported by compilers. Thus they are often not a good choice,
-especially when your code needs to be portable. And their capabilities are still
-limited.
-
-As a result, authors of such libraries often have to write scripts to generate
-their implementation. However, our experience is that it's tedious to write such
-scripts, which tend to reflect the structure of the generated code poorly and
-are often hard to read and edit. For example, a small change needed in the
-generated code may require some non-intuitive, non-trivial changes in the
-script. This is especially painful when experimenting with the code.
-
-# Our Solution
-
-Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta
-Programming, or Practical Utility for Meta Programming, whichever you prefer) is
-a simple meta-programming tool for C++. The idea is that a programmer writes a
-`foo.pump` file which contains C++ code plus meta code that manipulates the C++
-code. The meta code can handle iterations over a range, nested iterations, local
-meta variable definitions, simple arithmetic, and conditional expressions. You
-can view it as a small Domain-Specific Language. The meta language is designed
-to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and
-concise, making Pump code intuitive and easy to maintain.
-
-## Highlights
-
-* The implementation is in a single Python script and thus ultra portable: no
- build or installation is needed and it works cross platforms.
-* Pump tries to be smart with respect to
- [Google's style guide](https://github.com/google/styleguide): it breaks long
- lines (easy to have when they are generated) at acceptable places to fit
- within 80 columns and indent the continuation lines correctly.
-* The format is human-readable and more concise than XML.
-* The format works relatively well with Emacs' C++ mode.
-
-## Examples
-
-The following Pump code (where meta keywords start with `$`, `[[` and `]]` are
-meta brackets, and `$$` starts a meta comment that ends with the line):
-
-```
-$var n = 3 $$ Defines a meta variable n.
-$range i 0..n $$ Declares the range of meta iterator i (inclusive).
-$for i [[
- $$ Meta loop.
-// Foo$i does blah for $i-ary predicates.
-$range j 1..i
-template <size_t N $for j [[, typename A$j]]>
-class Foo$i {
-$if i == 0 [[
- blah a;
-]] $elif i <= 2 [[
- blah b;
-]] $else [[
- blah c;
-]]
-};
-
-]]
-```
-
-will be translated by the Pump compiler to:
-
-```cpp
-// Foo0 does blah for 0-ary predicates.
-template <size_t N>
-class Foo0 {
- blah a;
-};
-
-// Foo1 does blah for 1-ary predicates.
-template <size_t N, typename A1>
-class Foo1 {
- blah b;
-};
-
-// Foo2 does blah for 2-ary predicates.
-template <size_t N, typename A1, typename A2>
-class Foo2 {
- blah b;
-};
-
-// Foo3 does blah for 3-ary predicates.
-template <size_t N, typename A1, typename A2, typename A3>
-class Foo3 {
- blah c;
-};
-```
-
-In another example,
-
-```
-$range i 1..n
-Func($for i + [[a$i]]);
-$$ The text between i and [[ is the separator between iterations.
-```
-
-will generate one of the following lines (without the comments), depending on
-the value of `n`:
-
-```cpp
-Func(); // If n is 0.
-Func(a1); // If n is 1.
-Func(a1 + a2); // If n is 2.
-Func(a1 + a2 + a3); // If n is 3.
-// And so on...
-```
-
-## Constructs
-
-We support the following meta programming constructs:
-
-| `$var id = exp` | Defines a named constant value. `$id` is |
-: : valid util the end of the current meta :
-: : lexical block. :
-| :------------------------------- | :--------------------------------------- |
-| `$range id exp..exp` | Sets the range of an iteration variable, |
-: : which can be reused in multiple loops :
-: : later. :
-| `$for id sep [[ code ]]` | Iteration. The range of `id` must have |
-: : been defined earlier. `$id` is valid in :
-: : `code`. :
-| `$($)` | Generates a single `$` character. |
-| `$id` | Value of the named constant or iteration |
-: : variable. :
-| `$(exp)` | Value of the expression. |
-| `$if exp [[ code ]] else_branch` | Conditional. |
-| `[[ code ]]` | Meta lexical block. |
-| `cpp_code` | Raw C++ code. |
-| `$$ comment` | Meta comment. |
-
-**Note:** To give the user some freedom in formatting the Pump source code, Pump
-ignores a new-line character if it's right after `$for foo` or next to `[[` or
-`]]`. Without this rule you'll often be forced to write very long lines to get
-the desired output. Therefore sometimes you may need to insert an extra new-line
-in such places for a new-line to show up in your output.
-
-## Grammar
-
-```ebnf
-code ::= atomic_code*
-atomic_code ::= $var id = exp
- | $var id = [[ code ]]
- | $range id exp..exp
- | $for id sep [[ code ]]
- | $($)
- | $id
- | $(exp)
- | $if exp [[ code ]] else_branch
- | [[ code ]]
- | cpp_code
-sep ::= cpp_code | empty_string
-else_branch ::= $else [[ code ]]
- | $elif exp [[ code ]] else_branch
- | empty_string
-exp ::= simple_expression_in_Python_syntax
-```
-
-## Code
-
-You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py).
-It is still very unpolished and lacks automated tests, although it has been
-successfully used many times. If you find a chance to use it in your project,
-please let us know what you think! We also welcome help on improving Pump.
-
-## Real Examples
-
-You can find real-world applications of Pump in
-[Google Test](https://github.com/google/googletest/tree/master/googletest) and
-[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The
-source file `foo.h.pump` generates `foo.h`.
-
-## Tips
-
-* If a meta variable is followed by a letter or digit, you can separate them
- using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper`
- generate `Foo1Helper` when `j` is 1.
-* To avoid extra-long Pump source lines, you can break a line anywhere you
- want by inserting `[[]]` followed by a new line. Since any new-line
- character next to `[[` or `]]` is ignored, the generated code won't contain
- this new line.
+++ /dev/null
-# Googletest Samples {#samples}
-
-If you're like us, you'd like to look at
-[googletest samples.](https://github.com/google/googletest/tree/master/googletest/samples)
-The sample directory has a number of well-commented samples showing how to use a
-variety of googletest features.
-
-* Sample #1 shows the basic steps of using googletest to test C++ functions.
-* Sample #2 shows a more complex unit test for a class with multiple member
- functions.
-* Sample #3 uses a test fixture.
-* Sample #4 teaches you how to use googletest and `googletest.h` together to
- get the best of both libraries.
-* Sample #5 puts shared testing logic in a base test fixture, and reuses it in
- derived fixtures.
-* Sample #6 demonstrates type-parameterized tests.
-* Sample #7 teaches the basics of value-parameterized tests.
-* Sample #8 shows using `Combine()` in value-parameterized tests.
-* Sample #9 shows use of the listener API to modify Google Test's console
- output and the use of its reflection API to inspect test results.
-* Sample #10 shows use of the listener API to implement a primitive memory
- leak checker.
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file defines the public API for death tests. It is
-// #included by gtest.h so a user doesn't need to include this
-// directly.
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
-#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
-
-#include "gtest/internal/gtest-death-test-internal.h"
-
-namespace testing {
-
-// This flag controls the style of death tests. Valid values are "threadsafe",
-// meaning that the death test child process will re-execute the test binary
-// from the start, running only a single death test, or "fast",
-// meaning that the child process will execute the test logic immediately
-// after forking.
-GTEST_DECLARE_string_(death_test_style);
-
-#if GTEST_HAS_DEATH_TEST
-
-namespace internal {
-
-// Returns a Boolean value indicating whether the caller is currently
-// executing in the context of the death test child process. Tools such as
-// Valgrind heap checkers may need this to modify their behavior in death
-// tests. IMPORTANT: This is an internal utility. Using it may break the
-// implementation of death tests. User code MUST NOT use it.
-GTEST_API_ bool InDeathTestChild();
-
-} // namespace internal
-
-// The following macros are useful for writing death tests.
-
-// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
-// executed:
-//
-// 1. It generates a warning if there is more than one active
-// thread. This is because it's safe to fork() or clone() only
-// when there is a single thread.
-//
-// 2. The parent process clone()s a sub-process and runs the death
-// test in it; the sub-process exits with code 0 at the end of the
-// death test, if it hasn't exited already.
-//
-// 3. The parent process waits for the sub-process to terminate.
-//
-// 4. The parent process checks the exit code and error message of
-// the sub-process.
-//
-// Examples:
-//
-// ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
-// for (int i = 0; i < 5; i++) {
-// EXPECT_DEATH(server.ProcessRequest(i),
-// "Invalid request .* in ProcessRequest()")
-// << "Failed to die on request " << i;
-// }
-//
-// ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
-//
-// bool KilledBySIGHUP(int exit_code) {
-// return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
-// }
-//
-// ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
-//
-// On the regular expressions used in death tests:
-//
-// GOOGLETEST_CM0005 DO NOT DELETE
-// On POSIX-compliant systems (*nix), we use the <regex.h> library,
-// which uses the POSIX extended regex syntax.
-//
-// On other platforms (e.g. Windows or Mac), we only support a simple regex
-// syntax implemented as part of Google Test. This limited
-// implementation should be enough most of the time when writing
-// death tests; though it lacks many features you can find in PCRE
-// or POSIX extended regex syntax. For example, we don't support
-// union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
-// repetition count ("x{5,7}"), among others.
-//
-// Below is the syntax that we do support. We chose it to be a
-// subset of both PCRE and POSIX extended regex, so it's easy to
-// learn wherever you come from. In the following: 'A' denotes a
-// literal character, period (.), or a single \\ escape sequence;
-// 'x' and 'y' denote regular expressions; 'm' and 'n' are for
-// natural numbers.
-//
-// c matches any literal character c
-// \\d matches any decimal digit
-// \\D matches any character that's not a decimal digit
-// \\f matches \f
-// \\n matches \n
-// \\r matches \r
-// \\s matches any ASCII whitespace, including \n
-// \\S matches any character that's not a whitespace
-// \\t matches \t
-// \\v matches \v
-// \\w matches any letter, _, or decimal digit
-// \\W matches any character that \\w doesn't match
-// \\c matches any literal character c, which must be a punctuation
-// . matches any single character except \n
-// A? matches 0 or 1 occurrences of A
-// A* matches 0 or many occurrences of A
-// A+ matches 1 or many occurrences of A
-// ^ matches the beginning of a string (not that of each line)
-// $ matches the end of a string (not that of each line)
-// xy matches x followed by y
-//
-// If you accidentally use PCRE or POSIX extended regex features
-// not implemented by us, you will get a run-time failure. In that
-// case, please try to rewrite your regular expression within the
-// above syntax.
-//
-// This implementation is *not* meant to be as highly tuned or robust
-// as a compiled regex library, but should perform well enough for a
-// death test, which already incurs significant overhead by launching
-// a child process.
-//
-// Known caveats:
-//
-// A "threadsafe" style death test obtains the path to the test
-// program from argv[0] and re-executes it in the sub-process. For
-// simplicity, the current implementation doesn't search the PATH
-// when launching the sub-process. This means that the user must
-// invoke the test program via a path that contains at least one
-// path separator (e.g. path/to/foo_test and
-// /absolute/path/to/bar_test are fine, but foo_test is not). This
-// is rarely a problem as people usually don't put the test binary
-// directory in PATH.
-//
-
-// Asserts that a given statement causes the program to exit, with an
-// integer exit status that satisfies predicate, and emitting error output
-// that matches regex.
-# define ASSERT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
-
-// Like ASSERT_EXIT, but continues on to successive tests in the
-// test suite, if any:
-# define EXPECT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
-
-// Asserts that a given statement causes the program to exit, either by
-// explicitly exiting with a nonzero exit code or being killed by a
-// signal, and emitting error output that matches regex.
-# define ASSERT_DEATH(statement, regex) \
- ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
-
-// Like ASSERT_DEATH, but continues on to successive tests in the
-// test suite, if any:
-# define EXPECT_DEATH(statement, regex) \
- EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
-
-// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
-
-// Tests that an exit code describes a normal exit with a given exit code.
-class GTEST_API_ ExitedWithCode {
- public:
- explicit ExitedWithCode(int exit_code);
- bool operator()(int exit_status) const;
- private:
- // No implementation - assignment is unsupported.
- void operator=(const ExitedWithCode& other);
-
- const int exit_code_;
-};
-
-# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
-// Tests that an exit code describes an exit due to termination by a
-// given signal.
-// GOOGLETEST_CM0006 DO NOT DELETE
-class GTEST_API_ KilledBySignal {
- public:
- explicit KilledBySignal(int signum);
- bool operator()(int exit_status) const;
- private:
- const int signum_;
-};
-# endif // !GTEST_OS_WINDOWS
-
-// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
-// The death testing framework causes this to have interesting semantics,
-// since the sideeffects of the call are only visible in opt mode, and not
-// in debug mode.
-//
-// In practice, this can be used to test functions that utilize the
-// LOG(DFATAL) macro using the following style:
-//
-// int DieInDebugOr12(int* sideeffect) {
-// if (sideeffect) {
-// *sideeffect = 12;
-// }
-// LOG(DFATAL) << "death";
-// return 12;
-// }
-//
-// TEST(TestSuite, TestDieOr12WorksInDgbAndOpt) {
-// int sideeffect = 0;
-// // Only asserts in dbg.
-// EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
-//
-// #ifdef NDEBUG
-// // opt-mode has sideeffect visible.
-// EXPECT_EQ(12, sideeffect);
-// #else
-// // dbg-mode no visible sideeffect.
-// EXPECT_EQ(0, sideeffect);
-// #endif
-// }
-//
-// This will assert that DieInDebugReturn12InOpt() crashes in debug
-// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
-// appropriate fallback value (12 in this case) in opt mode. If you
-// need to test that a function has appropriate side-effects in opt
-// mode, include assertions against the side-effects. A general
-// pattern for this is:
-//
-// EXPECT_DEBUG_DEATH({
-// // Side-effects here will have an effect after this statement in
-// // opt mode, but none in debug mode.
-// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
-// }, "death");
-//
-# ifdef NDEBUG
-
-# define EXPECT_DEBUG_DEATH(statement, regex) \
- GTEST_EXECUTE_STATEMENT_(statement, regex)
-
-# define ASSERT_DEBUG_DEATH(statement, regex) \
- GTEST_EXECUTE_STATEMENT_(statement, regex)
-
-# else
-
-# define EXPECT_DEBUG_DEATH(statement, regex) \
- EXPECT_DEATH(statement, regex)
-
-# define ASSERT_DEBUG_DEATH(statement, regex) \
- ASSERT_DEATH(statement, regex)
-
-# endif // NDEBUG for EXPECT_DEBUG_DEATH
-#endif // GTEST_HAS_DEATH_TEST
-
-// This macro is used for implementing macros such as
-// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
-// death tests are not supported. Those macros must compile on such systems
-// if and only if EXPECT_DEATH and ASSERT_DEATH compile with the same parameters
-// on systems that support death tests. This allows one to write such a macro on
-// a system that does not support death tests and be sure that it will compile
-// on a death-test supporting system. It is exposed publicly so that systems
-// that have death-tests with stricter requirements than GTEST_HAS_DEATH_TEST
-// can write their own equivalent of EXPECT_DEATH_IF_SUPPORTED and
-// ASSERT_DEATH_IF_SUPPORTED.
-//
-// Parameters:
-// statement - A statement that a macro such as EXPECT_DEATH would test
-// for program termination. This macro has to make sure this
-// statement is compiled but not executed, to ensure that
-// EXPECT_DEATH_IF_SUPPORTED compiles with a certain
-// parameter if and only if EXPECT_DEATH compiles with it.
-// regex - A regex that a macro such as EXPECT_DEATH would use to test
-// the output of statement. This parameter has to be
-// compiled but not evaluated by this macro, to ensure that
-// this macro only accepts expressions that a macro such as
-// EXPECT_DEATH would accept.
-// terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
-// and a return statement for ASSERT_DEATH_IF_SUPPORTED.
-// This ensures that ASSERT_DEATH_IF_SUPPORTED will not
-// compile inside functions where ASSERT_DEATH doesn't
-// compile.
-//
-// The branch that has an always false condition is used to ensure that
-// statement and regex are compiled (and thus syntactically correct) but
-// never executed. The unreachable code macro protects the terminator
-// statement from generating an 'unreachable code' warning in case
-// statement unconditionally returns or throws. The Message constructor at
-// the end allows the syntax of streaming additional messages into the
-// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
-# define GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, terminator) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::AlwaysTrue()) { \
- GTEST_LOG_(WARNING) \
- << "Death tests are not supported on this platform.\n" \
- << "Statement '" #statement "' cannot be verified."; \
- } else if (::testing::internal::AlwaysFalse()) { \
- ::testing::internal::RE::PartialMatch(".*", (regex)); \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- terminator; \
- } else \
- ::testing::Message()
-
-// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
-// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
-// death tests are supported; otherwise they just issue a warning. This is
-// useful when you are combining death test assertions with normal test
-// assertions in one test.
-#if GTEST_HAS_DEATH_TEST
-# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
- EXPECT_DEATH(statement, regex)
-# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
- ASSERT_DEATH(statement, regex)
-#else
-# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
- GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, )
-# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
- GTEST_UNSUPPORTED_DEATH_TEST(statement, regex, return)
-#endif
-
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This file implements just enough of the matcher interface to allow
-// EXPECT_DEATH and friends to accept a matcher argument.
-
-// IWYU pragma: private, include "testing/base/public/gunit.h"
-// IWYU pragma: friend third_party/googletest/googlemock/.*
-// IWYU pragma: friend third_party/googletest/googletest/.*
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
-#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
-
-#include <memory>
-#include <ostream>
-#include <string>
-#include <type_traits>
-
-#include "gtest/gtest-printers.h"
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-port.h"
-
-// MSVC warning C5046 is new as of VS2017 version 15.8.
-#if defined(_MSC_VER) && _MSC_VER >= 1915
-#define GTEST_MAYBE_5046_ 5046
-#else
-#define GTEST_MAYBE_5046_
-#endif
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(
- 4251 GTEST_MAYBE_5046_ /* class A needs to have dll-interface to be used by
- clients of class B */
- /* Symbol involving type with internal linkage not defined */)
-
-namespace testing {
-
-// To implement a matcher Foo for type T, define:
-// 1. a class FooMatcherImpl that implements the
-// MatcherInterface<T> interface, and
-// 2. a factory function that creates a Matcher<T> object from a
-// FooMatcherImpl*.
-//
-// The two-level delegation design makes it possible to allow a user
-// to write "v" instead of "Eq(v)" where a Matcher is expected, which
-// is impossible if we pass matchers by pointers. It also eases
-// ownership management as Matcher objects can now be copied like
-// plain values.
-
-// MatchResultListener is an abstract class. Its << operator can be
-// used by a matcher to explain why a value matches or doesn't match.
-//
-class MatchResultListener {
- public:
- // Creates a listener object with the given underlying ostream. The
- // listener does not own the ostream, and does not dereference it
- // in the constructor or destructor.
- explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
- virtual ~MatchResultListener() = 0; // Makes this class abstract.
-
- // Streams x to the underlying ostream; does nothing if the ostream
- // is NULL.
- template <typename T>
- MatchResultListener& operator<<(const T& x) {
- if (stream_ != nullptr) *stream_ << x;
- return *this;
- }
-
- // Returns the underlying ostream.
- ::std::ostream* stream() { return stream_; }
-
- // Returns true if and only if the listener is interested in an explanation
- // of the match result. A matcher's MatchAndExplain() method can use
- // this information to avoid generating the explanation when no one
- // intends to hear it.
- bool IsInterested() const { return stream_ != nullptr; }
-
- private:
- ::std::ostream* const stream_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
-};
-
-inline MatchResultListener::~MatchResultListener() {
-}
-
-// An instance of a subclass of this knows how to describe itself as a
-// matcher.
-class MatcherDescriberInterface {
- public:
- virtual ~MatcherDescriberInterface() {}
-
- // Describes this matcher to an ostream. The function should print
- // a verb phrase that describes the property a value matching this
- // matcher should have. The subject of the verb phrase is the value
- // being matched. For example, the DescribeTo() method of the Gt(7)
- // matcher prints "is greater than 7".
- virtual void DescribeTo(::std::ostream* os) const = 0;
-
- // Describes the negation of this matcher to an ostream. For
- // example, if the description of this matcher is "is greater than
- // 7", the negated description could be "is not greater than 7".
- // You are not required to override this when implementing
- // MatcherInterface, but it is highly advised so that your matcher
- // can produce good error messages.
- virtual void DescribeNegationTo(::std::ostream* os) const {
- *os << "not (";
- DescribeTo(os);
- *os << ")";
- }
-};
-
-// The implementation of a matcher.
-template <typename T>
-class MatcherInterface : public MatcherDescriberInterface {
- public:
- // Returns true if and only if the matcher matches x; also explains the
- // match result to 'listener' if necessary (see the next paragraph), in
- // the form of a non-restrictive relative clause ("which ...",
- // "whose ...", etc) that describes x. For example, the
- // MatchAndExplain() method of the Pointee(...) matcher should
- // generate an explanation like "which points to ...".
- //
- // Implementations of MatchAndExplain() should add an explanation of
- // the match result *if and only if* they can provide additional
- // information that's not already present (or not obvious) in the
- // print-out of x and the matcher's description. Whether the match
- // succeeds is not a factor in deciding whether an explanation is
- // needed, as sometimes the caller needs to print a failure message
- // when the match succeeds (e.g. when the matcher is used inside
- // Not()).
- //
- // For example, a "has at least 10 elements" matcher should explain
- // what the actual element count is, regardless of the match result,
- // as it is useful information to the reader; on the other hand, an
- // "is empty" matcher probably only needs to explain what the actual
- // size is when the match fails, as it's redundant to say that the
- // size is 0 when the value is already known to be empty.
- //
- // You should override this method when defining a new matcher.
- //
- // It's the responsibility of the caller (Google Test) to guarantee
- // that 'listener' is not NULL. This helps to simplify a matcher's
- // implementation when it doesn't care about the performance, as it
- // can talk to 'listener' without checking its validity first.
- // However, in order to implement dummy listeners efficiently,
- // listener->stream() may be NULL.
- virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
-
- // Inherits these methods from MatcherDescriberInterface:
- // virtual void DescribeTo(::std::ostream* os) const = 0;
- // virtual void DescribeNegationTo(::std::ostream* os) const;
-};
-
-namespace internal {
-
-// Converts a MatcherInterface<T> to a MatcherInterface<const T&>.
-template <typename T>
-class MatcherInterfaceAdapter : public MatcherInterface<const T&> {
- public:
- explicit MatcherInterfaceAdapter(const MatcherInterface<T>* impl)
- : impl_(impl) {}
- ~MatcherInterfaceAdapter() override { delete impl_; }
-
- void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); }
-
- void DescribeNegationTo(::std::ostream* os) const override {
- impl_->DescribeNegationTo(os);
- }
-
- bool MatchAndExplain(const T& x,
- MatchResultListener* listener) const override {
- return impl_->MatchAndExplain(x, listener);
- }
-
- private:
- const MatcherInterface<T>* const impl_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter);
-};
-
-struct AnyEq {
- template <typename A, typename B>
- bool operator()(const A& a, const B& b) const { return a == b; }
-};
-struct AnyNe {
- template <typename A, typename B>
- bool operator()(const A& a, const B& b) const { return a != b; }
-};
-struct AnyLt {
- template <typename A, typename B>
- bool operator()(const A& a, const B& b) const { return a < b; }
-};
-struct AnyGt {
- template <typename A, typename B>
- bool operator()(const A& a, const B& b) const { return a > b; }
-};
-struct AnyLe {
- template <typename A, typename B>
- bool operator()(const A& a, const B& b) const { return a <= b; }
-};
-struct AnyGe {
- template <typename A, typename B>
- bool operator()(const A& a, const B& b) const { return a >= b; }
-};
-
-// A match result listener that ignores the explanation.
-class DummyMatchResultListener : public MatchResultListener {
- public:
- DummyMatchResultListener() : MatchResultListener(nullptr) {}
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
-};
-
-// A match result listener that forwards the explanation to a given
-// ostream. The difference between this and MatchResultListener is
-// that the former is concrete.
-class StreamMatchResultListener : public MatchResultListener {
- public:
- explicit StreamMatchResultListener(::std::ostream* os)
- : MatchResultListener(os) {}
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
-};
-
-// An internal class for implementing Matcher<T>, which will derive
-// from it. We put functionalities common to all Matcher<T>
-// specializations here to avoid code duplication.
-template <typename T>
-class MatcherBase {
- public:
- // Returns true if and only if the matcher matches x; also explains the
- // match result to 'listener'.
- bool MatchAndExplain(const T& x, MatchResultListener* listener) const {
- return impl_->MatchAndExplain(x, listener);
- }
-
- // Returns true if and only if this matcher matches x.
- bool Matches(const T& x) const {
- DummyMatchResultListener dummy;
- return MatchAndExplain(x, &dummy);
- }
-
- // Describes this matcher to an ostream.
- void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
-
- // Describes the negation of this matcher to an ostream.
- void DescribeNegationTo(::std::ostream* os) const {
- impl_->DescribeNegationTo(os);
- }
-
- // Explains why x matches, or doesn't match, the matcher.
- void ExplainMatchResultTo(const T& x, ::std::ostream* os) const {
- StreamMatchResultListener listener(os);
- MatchAndExplain(x, &listener);
- }
-
- // Returns the describer for this matcher object; retains ownership
- // of the describer, which is only guaranteed to be alive when
- // this matcher object is alive.
- const MatcherDescriberInterface* GetDescriber() const {
- return impl_.get();
- }
-
- protected:
- MatcherBase() {}
-
- // Constructs a matcher from its implementation.
- explicit MatcherBase(const MatcherInterface<const T&>* impl) : impl_(impl) {}
-
- template <typename U>
- explicit MatcherBase(
- const MatcherInterface<U>* impl,
- typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
- nullptr)
- : impl_(new internal::MatcherInterfaceAdapter<U>(impl)) {}
-
- MatcherBase(const MatcherBase&) = default;
- MatcherBase& operator=(const MatcherBase&) = default;
- MatcherBase(MatcherBase&&) = default;
- MatcherBase& operator=(MatcherBase&&) = default;
-
- virtual ~MatcherBase() {}
-
- private:
- std::shared_ptr<const MatcherInterface<const T&>> impl_;
-};
-
-} // namespace internal
-
-// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
-// object that can check whether a value of type T matches. The
-// implementation of Matcher<T> is just a std::shared_ptr to const
-// MatcherInterface<T>. Don't inherit from Matcher!
-template <typename T>
-class Matcher : public internal::MatcherBase<T> {
- public:
- // Constructs a null matcher. Needed for storing Matcher objects in STL
- // containers. A default-constructed matcher is not yet initialized. You
- // cannot use it until a valid value has been assigned to it.
- explicit Matcher() {} // NOLINT
-
- // Constructs a matcher from its implementation.
- explicit Matcher(const MatcherInterface<const T&>* impl)
- : internal::MatcherBase<T>(impl) {}
-
- template <typename U>
- explicit Matcher(
- const MatcherInterface<U>* impl,
- typename std::enable_if<!std::is_same<U, const U&>::value>::type* =
- nullptr)
- : internal::MatcherBase<T>(impl) {}
-
- // Implicit constructor here allows people to write
- // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
- Matcher(T value); // NOLINT
-};
-
-// The following two specializations allow the user to write str
-// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string
-// matcher is expected.
-template <>
-class GTEST_API_ Matcher<const std::string&>
- : public internal::MatcherBase<const std::string&> {
- public:
- Matcher() {}
-
- explicit Matcher(const MatcherInterface<const std::string&>* impl)
- : internal::MatcherBase<const std::string&>(impl) {}
-
- // Allows the user to write str instead of Eq(str) sometimes, where
- // str is a std::string object.
- Matcher(const std::string& s); // NOLINT
-
- // Allows the user to write "foo" instead of Eq("foo") sometimes.
- Matcher(const char* s); // NOLINT
-};
-
-template <>
-class GTEST_API_ Matcher<std::string>
- : public internal::MatcherBase<std::string> {
- public:
- Matcher() {}
-
- explicit Matcher(const MatcherInterface<const std::string&>* impl)
- : internal::MatcherBase<std::string>(impl) {}
- explicit Matcher(const MatcherInterface<std::string>* impl)
- : internal::MatcherBase<std::string>(impl) {}
-
- // Allows the user to write str instead of Eq(str) sometimes, where
- // str is a string object.
- Matcher(const std::string& s); // NOLINT
-
- // Allows the user to write "foo" instead of Eq("foo") sometimes.
- Matcher(const char* s); // NOLINT
-};
-
-#if GTEST_HAS_ABSL
-// The following two specializations allow the user to write str
-// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view
-// matcher is expected.
-template <>
-class GTEST_API_ Matcher<const absl::string_view&>
- : public internal::MatcherBase<const absl::string_view&> {
- public:
- Matcher() {}
-
- explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
- : internal::MatcherBase<const absl::string_view&>(impl) {}
-
- // Allows the user to write str instead of Eq(str) sometimes, where
- // str is a std::string object.
- Matcher(const std::string& s); // NOLINT
-
- // Allows the user to write "foo" instead of Eq("foo") sometimes.
- Matcher(const char* s); // NOLINT
-
- // Allows the user to pass absl::string_views directly.
- Matcher(absl::string_view s); // NOLINT
-};
-
-template <>
-class GTEST_API_ Matcher<absl::string_view>
- : public internal::MatcherBase<absl::string_view> {
- public:
- Matcher() {}
-
- explicit Matcher(const MatcherInterface<const absl::string_view&>* impl)
- : internal::MatcherBase<absl::string_view>(impl) {}
- explicit Matcher(const MatcherInterface<absl::string_view>* impl)
- : internal::MatcherBase<absl::string_view>(impl) {}
-
- // Allows the user to write str instead of Eq(str) sometimes, where
- // str is a std::string object.
- Matcher(const std::string& s); // NOLINT
-
- // Allows the user to write "foo" instead of Eq("foo") sometimes.
- Matcher(const char* s); // NOLINT
-
- // Allows the user to pass absl::string_views directly.
- Matcher(absl::string_view s); // NOLINT
-};
-#endif // GTEST_HAS_ABSL
-
-// Prints a matcher in a human-readable format.
-template <typename T>
-std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
- matcher.DescribeTo(&os);
- return os;
-}
-
-// The PolymorphicMatcher class template makes it easy to implement a
-// polymorphic matcher (i.e. a matcher that can match values of more
-// than one type, e.g. Eq(n) and NotNull()).
-//
-// To define a polymorphic matcher, a user should provide an Impl
-// class that has a DescribeTo() method and a DescribeNegationTo()
-// method, and define a member function (or member function template)
-//
-// bool MatchAndExplain(const Value& value,
-// MatchResultListener* listener) const;
-//
-// See the definition of NotNull() for a complete example.
-template <class Impl>
-class PolymorphicMatcher {
- public:
- explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
-
- // Returns a mutable reference to the underlying matcher
- // implementation object.
- Impl& mutable_impl() { return impl_; }
-
- // Returns an immutable reference to the underlying matcher
- // implementation object.
- const Impl& impl() const { return impl_; }
-
- template <typename T>
- operator Matcher<T>() const {
- return Matcher<T>(new MonomorphicImpl<const T&>(impl_));
- }
-
- private:
- template <typename T>
- class MonomorphicImpl : public MatcherInterface<T> {
- public:
- explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
-
- virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); }
-
- virtual void DescribeNegationTo(::std::ostream* os) const {
- impl_.DescribeNegationTo(os);
- }
-
- virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
- return impl_.MatchAndExplain(x, listener);
- }
-
- private:
- const Impl impl_;
- };
-
- Impl impl_;
-};
-
-// Creates a matcher from its implementation.
-// DEPRECATED: Especially in the generic code, prefer:
-// Matcher<T>(new MyMatcherImpl<const T&>(...));
-//
-// MakeMatcher may create a Matcher that accepts its argument by value, which
-// leads to unnecessary copies & lack of support for non-copyable types.
-template <typename T>
-inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
- return Matcher<T>(impl);
-}
-
-// Creates a polymorphic matcher from its implementation. This is
-// easier to use than the PolymorphicMatcher<Impl> constructor as it
-// doesn't require you to explicitly write the template argument, e.g.
-//
-// MakePolymorphicMatcher(foo);
-// vs
-// PolymorphicMatcher<TypeOfFoo>(foo);
-template <class Impl>
-inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
- return PolymorphicMatcher<Impl>(impl);
-}
-
-namespace internal {
-// Implements a matcher that compares a given value with a
-// pre-supplied value using one of the ==, <=, <, etc, operators. The
-// two values being compared don't have to have the same type.
-//
-// The matcher defined here is polymorphic (for example, Eq(5) can be
-// used to match an int, a short, a double, etc). Therefore we use
-// a template type conversion operator in the implementation.
-//
-// The following template definition assumes that the Rhs parameter is
-// a "bare" type (i.e. neither 'const T' nor 'T&').
-template <typename D, typename Rhs, typename Op>
-class ComparisonBase {
- public:
- explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {}
- template <typename Lhs>
- operator Matcher<Lhs>() const {
- return Matcher<Lhs>(new Impl<const Lhs&>(rhs_));
- }
-
- private:
- template <typename T>
- static const T& Unwrap(const T& v) { return v; }
- template <typename T>
- static const T& Unwrap(std::reference_wrapper<T> v) { return v; }
-
- template <typename Lhs, typename = Rhs>
- class Impl : public MatcherInterface<Lhs> {
- public:
- explicit Impl(const Rhs& rhs) : rhs_(rhs) {}
- bool MatchAndExplain(Lhs lhs,
- MatchResultListener* /* listener */) const override {
- return Op()(lhs, Unwrap(rhs_));
- }
- void DescribeTo(::std::ostream* os) const override {
- *os << D::Desc() << " ";
- UniversalPrint(Unwrap(rhs_), os);
- }
- void DescribeNegationTo(::std::ostream* os) const override {
- *os << D::NegatedDesc() << " ";
- UniversalPrint(Unwrap(rhs_), os);
- }
-
- private:
- Rhs rhs_;
- };
- Rhs rhs_;
-};
-
-template <typename Rhs>
-class EqMatcher : public ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq> {
- public:
- explicit EqMatcher(const Rhs& rhs)
- : ComparisonBase<EqMatcher<Rhs>, Rhs, AnyEq>(rhs) { }
- static const char* Desc() { return "is equal to"; }
- static const char* NegatedDesc() { return "isn't equal to"; }
-};
-template <typename Rhs>
-class NeMatcher : public ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe> {
- public:
- explicit NeMatcher(const Rhs& rhs)
- : ComparisonBase<NeMatcher<Rhs>, Rhs, AnyNe>(rhs) { }
- static const char* Desc() { return "isn't equal to"; }
- static const char* NegatedDesc() { return "is equal to"; }
-};
-template <typename Rhs>
-class LtMatcher : public ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt> {
- public:
- explicit LtMatcher(const Rhs& rhs)
- : ComparisonBase<LtMatcher<Rhs>, Rhs, AnyLt>(rhs) { }
- static const char* Desc() { return "is <"; }
- static const char* NegatedDesc() { return "isn't <"; }
-};
-template <typename Rhs>
-class GtMatcher : public ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt> {
- public:
- explicit GtMatcher(const Rhs& rhs)
- : ComparisonBase<GtMatcher<Rhs>, Rhs, AnyGt>(rhs) { }
- static const char* Desc() { return "is >"; }
- static const char* NegatedDesc() { return "isn't >"; }
-};
-template <typename Rhs>
-class LeMatcher : public ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe> {
- public:
- explicit LeMatcher(const Rhs& rhs)
- : ComparisonBase<LeMatcher<Rhs>, Rhs, AnyLe>(rhs) { }
- static const char* Desc() { return "is <="; }
- static const char* NegatedDesc() { return "isn't <="; }
-};
-template <typename Rhs>
-class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
- public:
- explicit GeMatcher(const Rhs& rhs)
- : ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe>(rhs) { }
- static const char* Desc() { return "is >="; }
- static const char* NegatedDesc() { return "isn't >="; }
-};
-
-// Implements polymorphic matchers MatchesRegex(regex) and
-// ContainsRegex(regex), which can be used as a Matcher<T> as long as
-// T can be converted to a string.
-class MatchesRegexMatcher {
- public:
- MatchesRegexMatcher(const RE* regex, bool full_match)
- : regex_(regex), full_match_(full_match) {}
-
-#if GTEST_HAS_ABSL
- bool MatchAndExplain(const absl::string_view& s,
- MatchResultListener* listener) const {
- return MatchAndExplain(std::string(s), listener);
- }
-#endif // GTEST_HAS_ABSL
-
- // Accepts pointer types, particularly:
- // const char*
- // char*
- // const wchar_t*
- // wchar_t*
- template <typename CharType>
- bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
- return s != nullptr && MatchAndExplain(std::string(s), listener);
- }
-
- // Matches anything that can convert to std::string.
- //
- // This is a template, not just a plain function with const std::string&,
- // because absl::string_view has some interfering non-explicit constructors.
- template <class MatcheeStringType>
- bool MatchAndExplain(const MatcheeStringType& s,
- MatchResultListener* /* listener */) const {
- const std::string& s2(s);
- return full_match_ ? RE::FullMatch(s2, *regex_)
- : RE::PartialMatch(s2, *regex_);
- }
-
- void DescribeTo(::std::ostream* os) const {
- *os << (full_match_ ? "matches" : "contains") << " regular expression ";
- UniversalPrinter<std::string>::Print(regex_->pattern(), os);
- }
-
- void DescribeNegationTo(::std::ostream* os) const {
- *os << "doesn't " << (full_match_ ? "match" : "contain")
- << " regular expression ";
- UniversalPrinter<std::string>::Print(regex_->pattern(), os);
- }
-
- private:
- const std::shared_ptr<const RE> regex_;
- const bool full_match_;
-};
-} // namespace internal
-
-// Matches a string that fully matches regular expression 'regex'.
-// The matcher takes ownership of 'regex'.
-inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
- const internal::RE* regex) {
- return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
-}
-inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
- const std::string& regex) {
- return MatchesRegex(new internal::RE(regex));
-}
-
-// Matches a string that contains regular expression 'regex'.
-// The matcher takes ownership of 'regex'.
-inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
- const internal::RE* regex) {
- return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
-}
-inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
- const std::string& regex) {
- return ContainsRegex(new internal::RE(regex));
-}
-
-// Creates a polymorphic matcher that matches anything equal to x.
-// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
-// wouldn't compile.
-template <typename T>
-inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
-
-// Constructs a Matcher<T> from a 'value' of type T. The constructed
-// matcher matches any value that's equal to 'value'.
-template <typename T>
-Matcher<T>::Matcher(T value) { *this = Eq(value); }
-
-// Creates a monomorphic matcher that matches anything with type Lhs
-// and equal to rhs. A user may need to use this instead of Eq(...)
-// in order to resolve an overloading ambiguity.
-//
-// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
-// or Matcher<T>(x), but more readable than the latter.
-//
-// We could define similar monomorphic matchers for other comparison
-// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
-// it yet as those are used much less than Eq() in practice. A user
-// can always write Matcher<T>(Lt(5)) to be explicit about the type,
-// for example.
-template <typename Lhs, typename Rhs>
-inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
-
-// Creates a polymorphic matcher that matches anything >= x.
-template <typename Rhs>
-inline internal::GeMatcher<Rhs> Ge(Rhs x) {
- return internal::GeMatcher<Rhs>(x);
-}
-
-// Creates a polymorphic matcher that matches anything > x.
-template <typename Rhs>
-inline internal::GtMatcher<Rhs> Gt(Rhs x) {
- return internal::GtMatcher<Rhs>(x);
-}
-
-// Creates a polymorphic matcher that matches anything <= x.
-template <typename Rhs>
-inline internal::LeMatcher<Rhs> Le(Rhs x) {
- return internal::LeMatcher<Rhs>(x);
-}
-
-// Creates a polymorphic matcher that matches anything < x.
-template <typename Rhs>
-inline internal::LtMatcher<Rhs> Lt(Rhs x) {
- return internal::LtMatcher<Rhs>(x);
-}
-
-// Creates a polymorphic matcher that matches anything != x.
-template <typename Rhs>
-inline internal::NeMatcher<Rhs> Ne(Rhs x) {
- return internal::NeMatcher<Rhs>(x);
-}
-} // namespace testing
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file defines the Message class.
-//
-// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
-// leave some internal implementation details in this header file.
-// They are clearly marked by comments like this:
-//
-// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-//
-// Such code is NOT meant to be used by a user directly, and is subject
-// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
-// program!
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
-#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
-
-#include <limits>
-#include <memory>
-
-#include "gtest/internal/gtest-port.h"
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-// Ensures that there is at least one operator<< in the global namespace.
-// See Message& operator<<(...) below for why.
-void operator<<(const testing::internal::Secret&, int);
-
-namespace testing {
-
-// The Message class works like an ostream repeater.
-//
-// Typical usage:
-//
-// 1. You stream a bunch of values to a Message object.
-// It will remember the text in a stringstream.
-// 2. Then you stream the Message object to an ostream.
-// This causes the text in the Message to be streamed
-// to the ostream.
-//
-// For example;
-//
-// testing::Message foo;
-// foo << 1 << " != " << 2;
-// std::cout << foo;
-//
-// will print "1 != 2".
-//
-// Message is not intended to be inherited from. In particular, its
-// destructor is not virtual.
-//
-// Note that stringstream behaves differently in gcc and in MSVC. You
-// can stream a NULL char pointer to it in the former, but not in the
-// latter (it causes an access violation if you do). The Message
-// class hides this difference by treating a NULL char pointer as
-// "(null)".
-class GTEST_API_ Message {
- private:
- // The type of basic IO manipulators (endl, ends, and flush) for
- // narrow streams.
- typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
-
- public:
- // Constructs an empty Message.
- Message();
-
- // Copy constructor.
- Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
- *ss_ << msg.GetString();
- }
-
- // Constructs a Message from a C-string.
- explicit Message(const char* str) : ss_(new ::std::stringstream) {
- *ss_ << str;
- }
-
- // Streams a non-pointer value to this object.
- template <typename T>
- inline Message& operator <<(const T& val) {
- // Some libraries overload << for STL containers. These
- // overloads are defined in the global namespace instead of ::std.
- //
- // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
- // overloads are visible in either the std namespace or the global
- // namespace, but not other namespaces, including the testing
- // namespace which Google Test's Message class is in.
- //
- // To allow STL containers (and other types that has a << operator
- // defined in the global namespace) to be used in Google Test
- // assertions, testing::Message must access the custom << operator
- // from the global namespace. With this using declaration,
- // overloads of << defined in the global namespace and those
- // visible via Koenig lookup are both exposed in this function.
- using ::operator <<;
- *ss_ << val;
- return *this;
- }
-
- // Streams a pointer value to this object.
- //
- // This function is an overload of the previous one. When you
- // stream a pointer to a Message, this definition will be used as it
- // is more specialized. (The C++ Standard, section
- // [temp.func.order].) If you stream a non-pointer, then the
- // previous definition will be used.
- //
- // The reason for this overload is that streaming a NULL pointer to
- // ostream is undefined behavior. Depending on the compiler, you
- // may get "0", "(nil)", "(null)", or an access violation. To
- // ensure consistent result across compilers, we always treat NULL
- // as "(null)".
- template <typename T>
- inline Message& operator <<(T* const& pointer) { // NOLINT
- if (pointer == nullptr) {
- *ss_ << "(null)";
- } else {
- *ss_ << pointer;
- }
- return *this;
- }
-
- // Since the basic IO manipulators are overloaded for both narrow
- // and wide streams, we have to provide this specialized definition
- // of operator <<, even though its body is the same as the
- // templatized version above. Without this definition, streaming
- // endl or other basic IO manipulators to Message will confuse the
- // compiler.
- Message& operator <<(BasicNarrowIoManip val) {
- *ss_ << val;
- return *this;
- }
-
- // Instead of 1/0, we want to see true/false for bool values.
- Message& operator <<(bool b) {
- return *this << (b ? "true" : "false");
- }
-
- // These two overloads allow streaming a wide C string to a Message
- // using the UTF-8 encoding.
- Message& operator <<(const wchar_t* wide_c_str);
- Message& operator <<(wchar_t* wide_c_str);
-
-#if GTEST_HAS_STD_WSTRING
- // Converts the given wide string to a narrow string using the UTF-8
- // encoding, and streams the result to this Message object.
- Message& operator <<(const ::std::wstring& wstr);
-#endif // GTEST_HAS_STD_WSTRING
-
- // Gets the text streamed to this object so far as an std::string.
- // Each '\0' character in the buffer is replaced with "\\0".
- //
- // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
- std::string GetString() const;
-
- private:
- // We'll hold the text streamed to this object here.
- const std::unique_ptr< ::std::stringstream> ss_;
-
- // We declare (but don't implement) this to prevent the compiler
- // from implementing the assignment operator.
- void operator=(const Message&);
-};
-
-// Streams a Message to an ostream.
-inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
- return os << sb.GetString();
-}
-
-namespace internal {
-
-// Converts a streamable value to an std::string. A NULL pointer is
-// converted to "(null)". When the input value is a ::string,
-// ::std::string, ::wstring, or ::std::wstring object, each NUL
-// character in it is replaced with "\\0".
-template <typename T>
-std::string StreamableToString(const T& streamable) {
- return (Message() << streamable).GetString();
-}
-
-} // namespace internal
-} // namespace testing
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Macros and functions for implementing parameterized tests
-// in Google C++ Testing and Mocking Framework (Google Test)
-//
-// This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
-//
-// GOOGLETEST_CM0001 DO NOT DELETE
-#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
-#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
-
-
-// Value-parameterized tests allow you to test your code with different
-// parameters without writing multiple copies of the same test.
-//
-// Here is how you use value-parameterized tests:
-
-#if 0
-
-// To write value-parameterized tests, first you should define a fixture
-// class. It is usually derived from testing::TestWithParam<T> (see below for
-// another inheritance scheme that's sometimes useful in more complicated
-// class hierarchies), where the type of your parameter values.
-// TestWithParam<T> is itself derived from testing::Test. T can be any
-// copyable type. If it's a raw pointer, you are responsible for managing the
-// lifespan of the pointed values.
-
-class FooTest : public ::testing::TestWithParam<const char*> {
- // You can implement all the usual class fixture members here.
-};
-
-// Then, use the TEST_P macro to define as many parameterized tests
-// for this fixture as you want. The _P suffix is for "parameterized"
-// or "pattern", whichever you prefer to think.
-
-TEST_P(FooTest, DoesBlah) {
- // Inside a test, access the test parameter with the GetParam() method
- // of the TestWithParam<T> class:
- EXPECT_TRUE(foo.Blah(GetParam()));
- ...
-}
-
-TEST_P(FooTest, HasBlahBlah) {
- ...
-}
-
-// Finally, you can use INSTANTIATE_TEST_SUITE_P to instantiate the test
-// case with any set of parameters you want. Google Test defines a number
-// of functions for generating test parameters. They return what we call
-// (surprise!) parameter generators. Here is a summary of them, which
-// are all in the testing namespace:
-//
-//
-// Range(begin, end [, step]) - Yields values {begin, begin+step,
-// begin+step+step, ...}. The values do not
-// include end. step defaults to 1.
-// Values(v1, v2, ..., vN) - Yields values {v1, v2, ..., vN}.
-// ValuesIn(container) - Yields values from a C-style array, an STL
-// ValuesIn(begin,end) container, or an iterator range [begin, end).
-// Bool() - Yields sequence {false, true}.
-// Combine(g1, g2, ..., gN) - Yields all combinations (the Cartesian product
-// for the math savvy) of the values generated
-// by the N generators.
-//
-// For more details, see comments at the definitions of these functions below
-// in this file.
-//
-// The following statement will instantiate tests from the FooTest test suite
-// each with parameter values "meeny", "miny", and "moe".
-
-INSTANTIATE_TEST_SUITE_P(InstantiationName,
- FooTest,
- Values("meeny", "miny", "moe"));
-
-// To distinguish different instances of the pattern, (yes, you
-// can instantiate it more than once) the first argument to the
-// INSTANTIATE_TEST_SUITE_P macro is a prefix that will be added to the
-// actual test suite name. Remember to pick unique prefixes for different
-// instantiations. The tests from the instantiation above will have
-// these names:
-//
-// * InstantiationName/FooTest.DoesBlah/0 for "meeny"
-// * InstantiationName/FooTest.DoesBlah/1 for "miny"
-// * InstantiationName/FooTest.DoesBlah/2 for "moe"
-// * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
-// * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
-// * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
-//
-// You can use these names in --gtest_filter.
-//
-// This statement will instantiate all tests from FooTest again, each
-// with parameter values "cat" and "dog":
-
-const char* pets[] = {"cat", "dog"};
-INSTANTIATE_TEST_SUITE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
-
-// The tests from the instantiation above will have these names:
-//
-// * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
-// * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
-// * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
-// * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
-//
-// Please note that INSTANTIATE_TEST_SUITE_P will instantiate all tests
-// in the given test suite, whether their definitions come before or
-// AFTER the INSTANTIATE_TEST_SUITE_P statement.
-//
-// Please also note that generator expressions (including parameters to the
-// generators) are evaluated in InitGoogleTest(), after main() has started.
-// This allows the user on one hand, to adjust generator parameters in order
-// to dynamically determine a set of tests to run and on the other hand,
-// give the user a chance to inspect the generated tests with Google Test
-// reflection API before RUN_ALL_TESTS() is executed.
-//
-// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
-// for more examples.
-//
-// In the future, we plan to publish the API for defining new parameter
-// generators. But for now this interface remains part of the internal
-// implementation and is subject to change.
-//
-//
-// A parameterized test fixture must be derived from testing::Test and from
-// testing::WithParamInterface<T>, where T is the type of the parameter
-// values. Inheriting from TestWithParam<T> satisfies that requirement because
-// TestWithParam<T> inherits from both Test and WithParamInterface. In more
-// complicated hierarchies, however, it is occasionally useful to inherit
-// separately from Test and WithParamInterface. For example:
-
-class BaseTest : public ::testing::Test {
- // You can inherit all the usual members for a non-parameterized test
- // fixture here.
-};
-
-class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
- // The usual test fixture members go here too.
-};
-
-TEST_F(BaseTest, HasFoo) {
- // This is an ordinary non-parameterized test.
-}
-
-TEST_P(DerivedTest, DoesBlah) {
- // GetParam works just the same here as if you inherit from TestWithParam.
- EXPECT_TRUE(foo.Blah(GetParam()));
-}
-
-#endif // 0
-
-#include <iterator>
-#include <utility>
-
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-param-util.h"
-#include "gtest/internal/gtest-port.h"
-
-namespace testing {
-
-// Functions producing parameter generators.
-//
-// Google Test uses these generators to produce parameters for value-
-// parameterized tests. When a parameterized test suite is instantiated
-// with a particular generator, Google Test creates and runs tests
-// for each element in the sequence produced by the generator.
-//
-// In the following sample, tests from test suite FooTest are instantiated
-// each three times with parameter values 3, 5, and 8:
-//
-// class FooTest : public TestWithParam<int> { ... };
-//
-// TEST_P(FooTest, TestThis) {
-// }
-// TEST_P(FooTest, TestThat) {
-// }
-// INSTANTIATE_TEST_SUITE_P(TestSequence, FooTest, Values(3, 5, 8));
-//
-
-// Range() returns generators providing sequences of values in a range.
-//
-// Synopsis:
-// Range(start, end)
-// - returns a generator producing a sequence of values {start, start+1,
-// start+2, ..., }.
-// Range(start, end, step)
-// - returns a generator producing a sequence of values {start, start+step,
-// start+step+step, ..., }.
-// Notes:
-// * The generated sequences never include end. For example, Range(1, 5)
-// returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
-// returns a generator producing {1, 3, 5, 7}.
-// * start and end must have the same type. That type may be any integral or
-// floating-point type or a user defined type satisfying these conditions:
-// * It must be assignable (have operator=() defined).
-// * It must have operator+() (operator+(int-compatible type) for
-// two-operand version).
-// * It must have operator<() defined.
-// Elements in the resulting sequences will also have that type.
-// * Condition start < end must be satisfied in order for resulting sequences
-// to contain any elements.
-//
-template <typename T, typename IncrementT>
-internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
- return internal::ParamGenerator<T>(
- new internal::RangeGenerator<T, IncrementT>(start, end, step));
-}
-
-template <typename T>
-internal::ParamGenerator<T> Range(T start, T end) {
- return Range(start, end, 1);
-}
-
-// ValuesIn() function allows generation of tests with parameters coming from
-// a container.
-//
-// Synopsis:
-// ValuesIn(const T (&array)[N])
-// - returns a generator producing sequences with elements from
-// a C-style array.
-// ValuesIn(const Container& container)
-// - returns a generator producing sequences with elements from
-// an STL-style container.
-// ValuesIn(Iterator begin, Iterator end)
-// - returns a generator producing sequences with elements from
-// a range [begin, end) defined by a pair of STL-style iterators. These
-// iterators can also be plain C pointers.
-//
-// Please note that ValuesIn copies the values from the containers
-// passed in and keeps them to generate tests in RUN_ALL_TESTS().
-//
-// Examples:
-//
-// This instantiates tests from test suite StringTest
-// each with C-string values of "foo", "bar", and "baz":
-//
-// const char* strings[] = {"foo", "bar", "baz"};
-// INSTANTIATE_TEST_SUITE_P(StringSequence, StringTest, ValuesIn(strings));
-//
-// This instantiates tests from test suite StlStringTest
-// each with STL strings with values "a" and "b":
-//
-// ::std::vector< ::std::string> GetParameterStrings() {
-// ::std::vector< ::std::string> v;
-// v.push_back("a");
-// v.push_back("b");
-// return v;
-// }
-//
-// INSTANTIATE_TEST_SUITE_P(CharSequence,
-// StlStringTest,
-// ValuesIn(GetParameterStrings()));
-//
-//
-// This will also instantiate tests from CharTest
-// each with parameter values 'a' and 'b':
-//
-// ::std::list<char> GetParameterChars() {
-// ::std::list<char> list;
-// list.push_back('a');
-// list.push_back('b');
-// return list;
-// }
-// ::std::list<char> l = GetParameterChars();
-// INSTANTIATE_TEST_SUITE_P(CharSequence2,
-// CharTest,
-// ValuesIn(l.begin(), l.end()));
-//
-template <typename ForwardIterator>
-internal::ParamGenerator<
- typename std::iterator_traits<ForwardIterator>::value_type>
-ValuesIn(ForwardIterator begin, ForwardIterator end) {
- typedef typename std::iterator_traits<ForwardIterator>::value_type ParamType;
- return internal::ParamGenerator<ParamType>(
- new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
-}
-
-template <typename T, size_t N>
-internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
- return ValuesIn(array, array + N);
-}
-
-template <class Container>
-internal::ParamGenerator<typename Container::value_type> ValuesIn(
- const Container& container) {
- return ValuesIn(container.begin(), container.end());
-}
-
-// Values() allows generating tests from explicitly specified list of
-// parameters.
-//
-// Synopsis:
-// Values(T v1, T v2, ..., T vN)
-// - returns a generator producing sequences with elements v1, v2, ..., vN.
-//
-// For example, this instantiates tests from test suite BarTest each
-// with values "one", "two", and "three":
-//
-// INSTANTIATE_TEST_SUITE_P(NumSequence,
-// BarTest,
-// Values("one", "two", "three"));
-//
-// This instantiates tests from test suite BazTest each with values 1, 2, 3.5.
-// The exact type of values will depend on the type of parameter in BazTest.
-//
-// INSTANTIATE_TEST_SUITE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
-//
-//
-template <typename... T>
-internal::ValueArray<T...> Values(T... v) {
- return internal::ValueArray<T...>(std::move(v)...);
-}
-
-// Bool() allows generating tests with parameters in a set of (false, true).
-//
-// Synopsis:
-// Bool()
-// - returns a generator producing sequences with elements {false, true}.
-//
-// It is useful when testing code that depends on Boolean flags. Combinations
-// of multiple flags can be tested when several Bool()'s are combined using
-// Combine() function.
-//
-// In the following example all tests in the test suite FlagDependentTest
-// will be instantiated twice with parameters false and true.
-//
-// class FlagDependentTest : public testing::TestWithParam<bool> {
-// virtual void SetUp() {
-// external_flag = GetParam();
-// }
-// }
-// INSTANTIATE_TEST_SUITE_P(BoolSequence, FlagDependentTest, Bool());
-//
-inline internal::ParamGenerator<bool> Bool() {
- return Values(false, true);
-}
-
-// Combine() allows the user to combine two or more sequences to produce
-// values of a Cartesian product of those sequences' elements.
-//
-// Synopsis:
-// Combine(gen1, gen2, ..., genN)
-// - returns a generator producing sequences with elements coming from
-// the Cartesian product of elements from the sequences generated by
-// gen1, gen2, ..., genN. The sequence elements will have a type of
-// std::tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
-// of elements from sequences produces by gen1, gen2, ..., genN.
-//
-// Combine can have up to 10 arguments.
-//
-// Example:
-//
-// This will instantiate tests in test suite AnimalTest each one with
-// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
-// tuple("dog", BLACK), and tuple("dog", WHITE):
-//
-// enum Color { BLACK, GRAY, WHITE };
-// class AnimalTest
-// : public testing::TestWithParam<std::tuple<const char*, Color> > {...};
-//
-// TEST_P(AnimalTest, AnimalLooksNice) {...}
-//
-// INSTANTIATE_TEST_SUITE_P(AnimalVariations, AnimalTest,
-// Combine(Values("cat", "dog"),
-// Values(BLACK, WHITE)));
-//
-// This will instantiate tests in FlagDependentTest with all variations of two
-// Boolean flags:
-//
-// class FlagDependentTest
-// : public testing::TestWithParam<std::tuple<bool, bool> > {
-// virtual void SetUp() {
-// // Assigns external_flag_1 and external_flag_2 values from the tuple.
-// std::tie(external_flag_1, external_flag_2) = GetParam();
-// }
-// };
-//
-// TEST_P(FlagDependentTest, TestFeature1) {
-// // Test your code using external_flag_1 and external_flag_2 here.
-// }
-// INSTANTIATE_TEST_SUITE_P(TwoBoolSequence, FlagDependentTest,
-// Combine(Bool(), Bool()));
-//
-template <typename... Generator>
-internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
- return internal::CartesianProductHolder<Generator...>(g...);
-}
-
-#define TEST_P(test_suite_name, test_name) \
- class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
- : public test_suite_name { \
- public: \
- GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
- virtual void TestBody(); \
- \
- private: \
- static int AddToRegistry() { \
- ::testing::UnitTest::GetInstance() \
- ->parameterized_test_registry() \
- .GetTestSuitePatternHolder<test_suite_name>( \
- #test_suite_name, \
- ::testing::internal::CodeLocation(__FILE__, __LINE__)) \
- ->AddTestPattern( \
- GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \
- new ::testing::internal::TestMetaFactory<GTEST_TEST_CLASS_NAME_( \
- test_suite_name, test_name)>()); \
- return 0; \
- } \
- static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
- GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
- test_name)); \
- }; \
- int GTEST_TEST_CLASS_NAME_(test_suite_name, \
- test_name)::gtest_registering_dummy_ = \
- GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::AddToRegistry(); \
- void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
-
-// The last argument to INSTANTIATE_TEST_SUITE_P allows the user to specify
-// generator and an optional function or functor that generates custom test name
-// suffixes based on the test parameters. Such a function or functor should
-// accept one argument of type testing::TestParamInfo<class ParamType>, and
-// return std::string.
-//
-// testing::PrintToStringParamName is a builtin test suffix generator that
-// returns the value of testing::PrintToString(GetParam()).
-//
-// Note: test names must be non-empty, unique, and may only contain ASCII
-// alphanumeric characters or underscore. Because PrintToString adds quotes
-// to std::string and C strings, it won't work for these types.
-
-#define GTEST_EXPAND_(arg) arg
-#define GTEST_GET_FIRST_(first, ...) first
-#define GTEST_GET_SECOND_(first, second, ...) second
-
-#define INSTANTIATE_TEST_SUITE_P(prefix, test_suite_name, ...) \
- static ::testing::internal::ParamGenerator<test_suite_name::ParamType> \
- gtest_##prefix##test_suite_name##_EvalGenerator_() { \
- return GTEST_EXPAND_(GTEST_GET_FIRST_(__VA_ARGS__, DUMMY_PARAM_)); \
- } \
- static ::std::string gtest_##prefix##test_suite_name##_EvalGenerateName_( \
- const ::testing::TestParamInfo<test_suite_name::ParamType>& info) { \
- if (::testing::internal::AlwaysFalse()) { \
- ::testing::internal::TestNotEmpty(GTEST_EXPAND_(GTEST_GET_SECOND_( \
- __VA_ARGS__, \
- ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
- DUMMY_PARAM_))); \
- auto t = std::make_tuple(__VA_ARGS__); \
- static_assert(std::tuple_size<decltype(t)>::value <= 2, \
- "Too Many Args!"); \
- } \
- return ((GTEST_EXPAND_(GTEST_GET_SECOND_( \
- __VA_ARGS__, \
- ::testing::internal::DefaultParamName<test_suite_name::ParamType>, \
- DUMMY_PARAM_))))(info); \
- } \
- static int gtest_##prefix##test_suite_name##_dummy_ \
- GTEST_ATTRIBUTE_UNUSED_ = \
- ::testing::UnitTest::GetInstance() \
- ->parameterized_test_registry() \
- .GetTestSuitePatternHolder<test_suite_name>( \
- #test_suite_name, \
- ::testing::internal::CodeLocation(__FILE__, __LINE__)) \
- ->AddTestSuiteInstantiation( \
- #prefix, >est_##prefix##test_suite_name##_EvalGenerator_, \
- >est_##prefix##test_suite_name##_EvalGenerateName_, \
- __FILE__, __LINE__)
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define INSTANTIATE_TEST_CASE_P \
- static_assert(::testing::internal::InstantiateTestCase_P_IsDeprecated(), \
- ""); \
- INSTANTIATE_TEST_SUITE_P
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Google Test - The Google C++ Testing and Mocking Framework
-//
-// This file implements a universal value printer that can print a
-// value of any type T:
-//
-// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
-//
-// A user can teach this function how to print a class type T by
-// defining either operator<<() or PrintTo() in the namespace that
-// defines T. More specifically, the FIRST defined function in the
-// following list will be used (assuming T is defined in namespace
-// foo):
-//
-// 1. foo::PrintTo(const T&, ostream*)
-// 2. operator<<(ostream&, const T&) defined in either foo or the
-// global namespace.
-//
-// However if T is an STL-style container then it is printed element-wise
-// unless foo::PrintTo(const T&, ostream*) is defined. Note that
-// operator<<() is ignored for container types.
-//
-// If none of the above is defined, it will print the debug string of
-// the value if it is a protocol buffer, or print the raw bytes in the
-// value otherwise.
-//
-// To aid debugging: when T is a reference type, the address of the
-// value is also printed; when T is a (const) char pointer, both the
-// pointer value and the NUL-terminated string it points to are
-// printed.
-//
-// We also provide some convenient wrappers:
-//
-// // Prints a value to a string. For a (const or not) char
-// // pointer, the NUL-terminated string (but not the pointer) is
-// // printed.
-// std::string ::testing::PrintToString(const T& value);
-//
-// // Prints a value tersely: for a reference type, the referenced
-// // value (but not the address) is printed; for a (const or not) char
-// // pointer, the NUL-terminated string (but not the pointer) is
-// // printed.
-// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
-//
-// // Prints value using the type inferred by the compiler. The difference
-// // from UniversalTersePrint() is that this function prints both the
-// // pointer and the NUL-terminated string for a (const or not) char pointer.
-// void ::testing::internal::UniversalPrint(const T& value, ostream*);
-//
-// // Prints the fields of a tuple tersely to a string vector, one
-// // element for each field. Tuple support must be enabled in
-// // gtest-port.h.
-// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
-// const Tuple& value);
-//
-// Known limitation:
-//
-// The print primitives print the elements of an STL-style container
-// using the compiler-inferred type of *iter where iter is a
-// const_iterator of the container. When const_iterator is an input
-// iterator but not a forward iterator, this inferred type may not
-// match value_type, and the print output may be incorrect. In
-// practice, this is rarely a problem as for most containers
-// const_iterator is a forward iterator. We'll fix this if there's an
-// actual need for it. Note that this fix cannot rely on value_type
-// being defined as many user-defined container types don't have
-// value_type.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
-#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
-
-#include <functional>
-#include <ostream> // NOLINT
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-#include <vector>
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-port.h"
-
-#if GTEST_HAS_ABSL
-#include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
-#include "absl/types/variant.h"
-#endif // GTEST_HAS_ABSL
-
-namespace testing {
-
-// Definitions in the 'internal' and 'internal2' name spaces are
-// subject to change without notice. DO NOT USE THEM IN USER CODE!
-namespace internal2 {
-
-// Prints the given number of bytes in the given object to the given
-// ostream.
-GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
- size_t count,
- ::std::ostream* os);
-
-// For selecting which printer to use when a given type has neither <<
-// nor PrintTo().
-enum TypeKind {
- kProtobuf, // a protobuf type
- kConvertibleToInteger, // a type implicitly convertible to BiggestInt
- // (e.g. a named or unnamed enum type)
-#if GTEST_HAS_ABSL
- kConvertibleToStringView, // a type implicitly convertible to
- // absl::string_view
-#endif
- kOtherType // anything else
-};
-
-// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
-// by the universal printer to print a value of type T when neither
-// operator<< nor PrintTo() is defined for T, where kTypeKind is the
-// "kind" of T as defined by enum TypeKind.
-template <typename T, TypeKind kTypeKind>
-class TypeWithoutFormatter {
- public:
- // This default version is called when kTypeKind is kOtherType.
- static void PrintValue(const T& value, ::std::ostream* os) {
- PrintBytesInObjectTo(
- static_cast<const unsigned char*>(
- reinterpret_cast<const void*>(std::addressof(value))),
- sizeof(value), os);
- }
-};
-
-// We print a protobuf using its ShortDebugString() when the string
-// doesn't exceed this many characters; otherwise we print it using
-// DebugString() for better readability.
-const size_t kProtobufOneLinerMaxLength = 50;
-
-template <typename T>
-class TypeWithoutFormatter<T, kProtobuf> {
- public:
- static void PrintValue(const T& value, ::std::ostream* os) {
- std::string pretty_str = value.ShortDebugString();
- if (pretty_str.length() > kProtobufOneLinerMaxLength) {
- pretty_str = "\n" + value.DebugString();
- }
- *os << ("<" + pretty_str + ">");
- }
-};
-
-template <typename T>
-class TypeWithoutFormatter<T, kConvertibleToInteger> {
- public:
- // Since T has no << operator or PrintTo() but can be implicitly
- // converted to BiggestInt, we print it as a BiggestInt.
- //
- // Most likely T is an enum type (either named or unnamed), in which
- // case printing it as an integer is the desired behavior. In case
- // T is not an enum, printing it as an integer is the best we can do
- // given that it has no user-defined printer.
- static void PrintValue(const T& value, ::std::ostream* os) {
- const internal::BiggestInt kBigInt = value;
- *os << kBigInt;
- }
-};
-
-#if GTEST_HAS_ABSL
-template <typename T>
-class TypeWithoutFormatter<T, kConvertibleToStringView> {
- public:
- // Since T has neither operator<< nor PrintTo() but can be implicitly
- // converted to absl::string_view, we print it as a absl::string_view.
- //
- // Note: the implementation is further below, as it depends on
- // internal::PrintTo symbol which is defined later in the file.
- static void PrintValue(const T& value, ::std::ostream* os);
-};
-#endif
-
-// Prints the given value to the given ostream. If the value is a
-// protocol message, its debug string is printed; if it's an enum or
-// of a type implicitly convertible to BiggestInt, it's printed as an
-// integer; otherwise the bytes in the value are printed. This is
-// what UniversalPrinter<T>::Print() does when it knows nothing about
-// type T and T has neither << operator nor PrintTo().
-//
-// A user can override this behavior for a class type Foo by defining
-// a << operator in the namespace where Foo is defined.
-//
-// We put this operator in namespace 'internal2' instead of 'internal'
-// to simplify the implementation, as much code in 'internal' needs to
-// use << in STL, which would conflict with our own << were it defined
-// in 'internal'.
-//
-// Note that this operator<< takes a generic std::basic_ostream<Char,
-// CharTraits> type instead of the more restricted std::ostream. If
-// we define it to take an std::ostream instead, we'll get an
-// "ambiguous overloads" compiler error when trying to print a type
-// Foo that supports streaming to std::basic_ostream<Char,
-// CharTraits>, as the compiler cannot tell whether
-// operator<<(std::ostream&, const T&) or
-// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
-// specific.
-template <typename Char, typename CharTraits, typename T>
-::std::basic_ostream<Char, CharTraits>& operator<<(
- ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
- TypeWithoutFormatter<T, (internal::IsAProtocolMessage<T>::value
- ? kProtobuf
- : std::is_convertible<
- const T&, internal::BiggestInt>::value
- ? kConvertibleToInteger
- :
-#if GTEST_HAS_ABSL
- std::is_convertible<
- const T&, absl::string_view>::value
- ? kConvertibleToStringView
- :
-#endif
- kOtherType)>::PrintValue(x, &os);
- return os;
-}
-
-} // namespace internal2
-} // namespace testing
-
-// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
-// magic needed for implementing UniversalPrinter won't work.
-namespace testing_internal {
-
-// Used to print a value that is not an STL-style container when the
-// user doesn't define PrintTo() for it.
-template <typename T>
-void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
- // With the following statement, during unqualified name lookup,
- // testing::internal2::operator<< appears as if it was declared in
- // the nearest enclosing namespace that contains both
- // ::testing_internal and ::testing::internal2, i.e. the global
- // namespace. For more details, refer to the C++ Standard section
- // 7.3.4-1 [namespace.udir]. This allows us to fall back onto
- // testing::internal2::operator<< in case T doesn't come with a <<
- // operator.
- //
- // We cannot write 'using ::testing::internal2::operator<<;', which
- // gcc 3.3 fails to compile due to a compiler bug.
- using namespace ::testing::internal2; // NOLINT
-
- // Assuming T is defined in namespace foo, in the next statement,
- // the compiler will consider all of:
- //
- // 1. foo::operator<< (thanks to Koenig look-up),
- // 2. ::operator<< (as the current namespace is enclosed in ::),
- // 3. testing::internal2::operator<< (thanks to the using statement above).
- //
- // The operator<< whose type matches T best will be picked.
- //
- // We deliberately allow #2 to be a candidate, as sometimes it's
- // impossible to define #1 (e.g. when foo is ::std, defining
- // anything in it is undefined behavior unless you are a compiler
- // vendor.).
- *os << value;
-}
-
-} // namespace testing_internal
-
-namespace testing {
-namespace internal {
-
-// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
-// value of type ToPrint that is an operand of a comparison assertion
-// (e.g. ASSERT_EQ). OtherOperand is the type of the other operand in
-// the comparison, and is used to help determine the best way to
-// format the value. In particular, when the value is a C string
-// (char pointer) and the other operand is an STL string object, we
-// want to format the C string as a string, since we know it is
-// compared by value with the string object. If the value is a char
-// pointer but the other operand is not an STL string object, we don't
-// know whether the pointer is supposed to point to a NUL-terminated
-// string, and thus want to print it as a pointer to be safe.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-
-// The default case.
-template <typename ToPrint, typename OtherOperand>
-class FormatForComparison {
- public:
- static ::std::string Format(const ToPrint& value) {
- return ::testing::PrintToString(value);
- }
-};
-
-// Array.
-template <typename ToPrint, size_t N, typename OtherOperand>
-class FormatForComparison<ToPrint[N], OtherOperand> {
- public:
- static ::std::string Format(const ToPrint* value) {
- return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
- }
-};
-
-// By default, print C string as pointers to be safe, as we don't know
-// whether they actually point to a NUL-terminated string.
-
-#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType) \
- template <typename OtherOperand> \
- class FormatForComparison<CharType*, OtherOperand> { \
- public: \
- static ::std::string Format(CharType* value) { \
- return ::testing::PrintToString(static_cast<const void*>(value)); \
- } \
- }
-
-GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
-GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
-GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
-GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
-
-#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
-
-// If a C string is compared with an STL string object, we know it's meant
-// to point to a NUL-terminated string, and thus can print it as a string.
-
-#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
- template <> \
- class FormatForComparison<CharType*, OtherStringType> { \
- public: \
- static ::std::string Format(CharType* value) { \
- return ::testing::PrintToString(value); \
- } \
- }
-
-GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
-GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
-
-#if GTEST_HAS_STD_WSTRING
-GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
-GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
-#endif
-
-#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
-
-// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
-// operand to be used in a failure message. The type (but not value)
-// of the other operand may affect the format. This allows us to
-// print a char* as a raw pointer when it is compared against another
-// char* or void*, and print it as a C string when it is compared
-// against an std::string object, for example.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-template <typename T1, typename T2>
-std::string FormatForComparisonFailureMessage(
- const T1& value, const T2& /* other_operand */) {
- return FormatForComparison<T1, T2>::Format(value);
-}
-
-// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
-// value to the given ostream. The caller must ensure that
-// 'ostream_ptr' is not NULL, or the behavior is undefined.
-//
-// We define UniversalPrinter as a class template (as opposed to a
-// function template), as we need to partially specialize it for
-// reference types, which cannot be done with function templates.
-template <typename T>
-class UniversalPrinter;
-
-template <typename T>
-void UniversalPrint(const T& value, ::std::ostream* os);
-
-enum DefaultPrinterType {
- kPrintContainer,
- kPrintPointer,
- kPrintFunctionPointer,
- kPrintOther,
-};
-template <DefaultPrinterType type> struct WrapPrinterType {};
-
-// Used to print an STL-style container when the user doesn't define
-// a PrintTo() for it.
-template <typename C>
-void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
- const C& container, ::std::ostream* os) {
- const size_t kMaxCount = 32; // The maximum number of elements to print.
- *os << '{';
- size_t count = 0;
- for (typename C::const_iterator it = container.begin();
- it != container.end(); ++it, ++count) {
- if (count > 0) {
- *os << ',';
- if (count == kMaxCount) { // Enough has been printed.
- *os << " ...";
- break;
- }
- }
- *os << ' ';
- // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
- // handle *it being a native array.
- internal::UniversalPrint(*it, os);
- }
-
- if (count > 0) {
- *os << ' ';
- }
- *os << '}';
-}
-
-// Used to print a pointer that is neither a char pointer nor a member
-// pointer, when the user doesn't define PrintTo() for it. (A member
-// variable pointer or member function pointer doesn't really point to
-// a location in the address space. Their representation is
-// implementation-defined. Therefore they will be printed as raw
-// bytes.)
-template <typename T>
-void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
- T* p, ::std::ostream* os) {
- if (p == nullptr) {
- *os << "NULL";
- } else {
- // T is not a function type. We just call << to print p,
- // relying on ADL to pick up user-defined << for their pointer
- // types, if any.
- *os << p;
- }
-}
-template <typename T>
-void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
- T* p, ::std::ostream* os) {
- if (p == nullptr) {
- *os << "NULL";
- } else {
- // T is a function type, so '*os << p' doesn't do what we want
- // (it just prints p as bool). We want to print p as a const
- // void*.
- *os << reinterpret_cast<const void*>(p);
- }
-}
-
-// Used to print a non-container, non-pointer value when the user
-// doesn't define PrintTo() for it.
-template <typename T>
-void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
- const T& value, ::std::ostream* os) {
- ::testing_internal::DefaultPrintNonContainerTo(value, os);
-}
-
-// Prints the given value using the << operator if it has one;
-// otherwise prints the bytes in it. This is what
-// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
-// or overloaded for type T.
-//
-// A user can override this behavior for a class type Foo by defining
-// an overload of PrintTo() in the namespace where Foo is defined. We
-// give the user this option as sometimes defining a << operator for
-// Foo is not desirable (e.g. the coding style may prevent doing it,
-// or there is already a << operator but it doesn't do what the user
-// wants).
-template <typename T>
-void PrintTo(const T& value, ::std::ostream* os) {
- // DefaultPrintTo() is overloaded. The type of its first argument
- // determines which version will be picked.
- //
- // Note that we check for container types here, prior to we check
- // for protocol message types in our operator<<. The rationale is:
- //
- // For protocol messages, we want to give people a chance to
- // override Google Mock's format by defining a PrintTo() or
- // operator<<. For STL containers, other formats can be
- // incompatible with Google Mock's format for the container
- // elements; therefore we check for container types here to ensure
- // that our format is used.
- //
- // Note that MSVC and clang-cl do allow an implicit conversion from
- // pointer-to-function to pointer-to-object, but clang-cl warns on it.
- // So don't use ImplicitlyConvertible if it can be helped since it will
- // cause this warning, and use a separate overload of DefaultPrintTo for
- // function pointers so that the `*os << p` in the object pointer overload
- // doesn't cause that warning either.
- DefaultPrintTo(
- WrapPrinterType <
- (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
- !IsRecursiveContainer<T>::value
- ? kPrintContainer
- : !std::is_pointer<T>::value
- ? kPrintOther
- : std::is_function<typename std::remove_pointer<T>::type>::value
- ? kPrintFunctionPointer
- : kPrintPointer > (),
- value, os);
-}
-
-// The following list of PrintTo() overloads tells
-// UniversalPrinter<T>::Print() how to print standard types (built-in
-// types, strings, plain arrays, and pointers).
-
-// Overloads for various char types.
-GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
-GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
-inline void PrintTo(char c, ::std::ostream* os) {
- // When printing a plain char, we always treat it as unsigned. This
- // way, the output won't be affected by whether the compiler thinks
- // char is signed or not.
- PrintTo(static_cast<unsigned char>(c), os);
-}
-
-// Overloads for other simple built-in types.
-inline void PrintTo(bool x, ::std::ostream* os) {
- *os << (x ? "true" : "false");
-}
-
-// Overload for wchar_t type.
-// Prints a wchar_t as a symbol if it is printable or as its internal
-// code otherwise and also as its decimal code (except for L'\0').
-// The L'\0' char is printed as "L'\\0'". The decimal code is printed
-// as signed integer when wchar_t is implemented by the compiler
-// as a signed type and is printed as an unsigned integer when wchar_t
-// is implemented as an unsigned type.
-GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
-
-// Overloads for C strings.
-GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
-inline void PrintTo(char* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const char*>(s), os);
-}
-
-// signed/unsigned char is often used for representing binary data, so
-// we print pointers to it as void* to be safe.
-inline void PrintTo(const signed char* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
-inline void PrintTo(signed char* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
-inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
-inline void PrintTo(unsigned char* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const void*>(s), os);
-}
-
-// MSVC can be configured to define wchar_t as a typedef of unsigned
-// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
-// type. When wchar_t is a typedef, defining an overload for const
-// wchar_t* would cause unsigned short* be printed as a wide string,
-// possibly causing invalid memory accesses.
-#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-// Overloads for wide C strings
-GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
-inline void PrintTo(wchar_t* s, ::std::ostream* os) {
- PrintTo(ImplicitCast_<const wchar_t*>(s), os);
-}
-#endif
-
-// Overload for C arrays. Multi-dimensional arrays are printed
-// properly.
-
-// Prints the given number of elements in an array, without printing
-// the curly braces.
-template <typename T>
-void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
- UniversalPrint(a[0], os);
- for (size_t i = 1; i != count; i++) {
- *os << ", ";
- UniversalPrint(a[i], os);
- }
-}
-
-// Overloads for ::std::string.
-GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
-inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
- PrintStringTo(s, os);
-}
-
-// Overloads for ::std::wstring.
-#if GTEST_HAS_STD_WSTRING
-GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
-inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
- PrintWideStringTo(s, os);
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-#if GTEST_HAS_ABSL
-// Overload for absl::string_view.
-inline void PrintTo(absl::string_view sp, ::std::ostream* os) {
- PrintTo(::std::string(sp), os);
-}
-#endif // GTEST_HAS_ABSL
-
-inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; }
-
-template <typename T>
-void PrintTo(std::reference_wrapper<T> ref, ::std::ostream* os) {
- UniversalPrinter<T&>::Print(ref.get(), os);
-}
-
-// Helper function for printing a tuple. T must be instantiated with
-// a tuple type.
-template <typename T>
-void PrintTupleTo(const T&, std::integral_constant<size_t, 0>,
- ::std::ostream*) {}
-
-template <typename T, size_t I>
-void PrintTupleTo(const T& t, std::integral_constant<size_t, I>,
- ::std::ostream* os) {
- PrintTupleTo(t, std::integral_constant<size_t, I - 1>(), os);
- GTEST_INTENTIONAL_CONST_COND_PUSH_()
- if (I > 1) {
- GTEST_INTENTIONAL_CONST_COND_POP_()
- *os << ", ";
- }
- UniversalPrinter<typename std::tuple_element<I - 1, T>::type>::Print(
- std::get<I - 1>(t), os);
-}
-
-template <typename... Types>
-void PrintTo(const ::std::tuple<Types...>& t, ::std::ostream* os) {
- *os << "(";
- PrintTupleTo(t, std::integral_constant<size_t, sizeof...(Types)>(), os);
- *os << ")";
-}
-
-// Overload for std::pair.
-template <typename T1, typename T2>
-void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
- *os << '(';
- // We cannot use UniversalPrint(value.first, os) here, as T1 may be
- // a reference type. The same for printing value.second.
- UniversalPrinter<T1>::Print(value.first, os);
- *os << ", ";
- UniversalPrinter<T2>::Print(value.second, os);
- *os << ')';
-}
-
-// Implements printing a non-reference type T by letting the compiler
-// pick the right overload of PrintTo() for T.
-template <typename T>
-class UniversalPrinter {
- public:
- // MSVC warns about adding const to a function type, so we want to
- // disable the warning.
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
-
- // Note: we deliberately don't call this PrintTo(), as that name
- // conflicts with ::testing::internal::PrintTo in the body of the
- // function.
- static void Print(const T& value, ::std::ostream* os) {
- // By default, ::testing::internal::PrintTo() is used for printing
- // the value.
- //
- // Thanks to Koenig look-up, if T is a class and has its own
- // PrintTo() function defined in its namespace, that function will
- // be visible here. Since it is more specific than the generic ones
- // in ::testing::internal, it will be picked by the compiler in the
- // following statement - exactly what we want.
- PrintTo(value, os);
- }
-
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-};
-
-#if GTEST_HAS_ABSL
-
-// Printer for absl::optional
-
-template <typename T>
-class UniversalPrinter<::absl::optional<T>> {
- public:
- static void Print(const ::absl::optional<T>& value, ::std::ostream* os) {
- *os << '(';
- if (!value) {
- *os << "nullopt";
- } else {
- UniversalPrint(*value, os);
- }
- *os << ')';
- }
-};
-
-// Printer for absl::variant
-
-template <typename... T>
-class UniversalPrinter<::absl::variant<T...>> {
- public:
- static void Print(const ::absl::variant<T...>& value, ::std::ostream* os) {
- *os << '(';
- absl::visit(Visitor{os}, value);
- *os << ')';
- }
-
- private:
- struct Visitor {
- template <typename U>
- void operator()(const U& u) const {
- *os << "'" << GetTypeName<U>() << "' with value ";
- UniversalPrint(u, os);
- }
- ::std::ostream* os;
- };
-};
-
-#endif // GTEST_HAS_ABSL
-
-// UniversalPrintArray(begin, len, os) prints an array of 'len'
-// elements, starting at address 'begin'.
-template <typename T>
-void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
- if (len == 0) {
- *os << "{}";
- } else {
- *os << "{ ";
- const size_t kThreshold = 18;
- const size_t kChunkSize = 8;
- // If the array has more than kThreshold elements, we'll have to
- // omit some details by printing only the first and the last
- // kChunkSize elements.
- if (len <= kThreshold) {
- PrintRawArrayTo(begin, len, os);
- } else {
- PrintRawArrayTo(begin, kChunkSize, os);
- *os << ", ..., ";
- PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
- }
- *os << " }";
- }
-}
-// This overload prints a (const) char array compactly.
-GTEST_API_ void UniversalPrintArray(
- const char* begin, size_t len, ::std::ostream* os);
-
-// This overload prints a (const) wchar_t array compactly.
-GTEST_API_ void UniversalPrintArray(
- const wchar_t* begin, size_t len, ::std::ostream* os);
-
-// Implements printing an array type T[N].
-template <typename T, size_t N>
-class UniversalPrinter<T[N]> {
- public:
- // Prints the given array, omitting some elements when there are too
- // many.
- static void Print(const T (&a)[N], ::std::ostream* os) {
- UniversalPrintArray(a, N, os);
- }
-};
-
-// Implements printing a reference type T&.
-template <typename T>
-class UniversalPrinter<T&> {
- public:
- // MSVC warns about adding const to a function type, so we want to
- // disable the warning.
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
-
- static void Print(const T& value, ::std::ostream* os) {
- // Prints the address of the value. We use reinterpret_cast here
- // as static_cast doesn't compile when T is a function type.
- *os << "@" << reinterpret_cast<const void*>(&value) << " ";
-
- // Then prints the value itself.
- UniversalPrint(value, os);
- }
-
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-};
-
-// Prints a value tersely: for a reference type, the referenced value
-// (but not the address) is printed; for a (const) char pointer, the
-// NUL-terminated string (but not the pointer) is printed.
-
-template <typename T>
-class UniversalTersePrinter {
- public:
- static void Print(const T& value, ::std::ostream* os) {
- UniversalPrint(value, os);
- }
-};
-template <typename T>
-class UniversalTersePrinter<T&> {
- public:
- static void Print(const T& value, ::std::ostream* os) {
- UniversalPrint(value, os);
- }
-};
-template <typename T, size_t N>
-class UniversalTersePrinter<T[N]> {
- public:
- static void Print(const T (&value)[N], ::std::ostream* os) {
- UniversalPrinter<T[N]>::Print(value, os);
- }
-};
-template <>
-class UniversalTersePrinter<const char*> {
- public:
- static void Print(const char* str, ::std::ostream* os) {
- if (str == nullptr) {
- *os << "NULL";
- } else {
- UniversalPrint(std::string(str), os);
- }
- }
-};
-template <>
-class UniversalTersePrinter<char*> {
- public:
- static void Print(char* str, ::std::ostream* os) {
- UniversalTersePrinter<const char*>::Print(str, os);
- }
-};
-
-#if GTEST_HAS_STD_WSTRING
-template <>
-class UniversalTersePrinter<const wchar_t*> {
- public:
- static void Print(const wchar_t* str, ::std::ostream* os) {
- if (str == nullptr) {
- *os << "NULL";
- } else {
- UniversalPrint(::std::wstring(str), os);
- }
- }
-};
-#endif
-
-template <>
-class UniversalTersePrinter<wchar_t*> {
- public:
- static void Print(wchar_t* str, ::std::ostream* os) {
- UniversalTersePrinter<const wchar_t*>::Print(str, os);
- }
-};
-
-template <typename T>
-void UniversalTersePrint(const T& value, ::std::ostream* os) {
- UniversalTersePrinter<T>::Print(value, os);
-}
-
-// Prints a value using the type inferred by the compiler. The
-// difference between this and UniversalTersePrint() is that for a
-// (const) char pointer, this prints both the pointer and the
-// NUL-terminated string.
-template <typename T>
-void UniversalPrint(const T& value, ::std::ostream* os) {
- // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
- // UniversalPrinter with T directly.
- typedef T T1;
- UniversalPrinter<T1>::Print(value, os);
-}
-
-typedef ::std::vector< ::std::string> Strings;
-
- // Tersely prints the first N fields of a tuple to a string vector,
- // one element for each field.
-template <typename Tuple>
-void TersePrintPrefixToStrings(const Tuple&, std::integral_constant<size_t, 0>,
- Strings*) {}
-template <typename Tuple, size_t I>
-void TersePrintPrefixToStrings(const Tuple& t,
- std::integral_constant<size_t, I>,
- Strings* strings) {
- TersePrintPrefixToStrings(t, std::integral_constant<size_t, I - 1>(),
- strings);
- ::std::stringstream ss;
- UniversalTersePrint(std::get<I - 1>(t), &ss);
- strings->push_back(ss.str());
-}
-
-// Prints the fields of a tuple tersely to a string vector, one
-// element for each field. See the comment before
-// UniversalTersePrint() for how we define "tersely".
-template <typename Tuple>
-Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
- Strings result;
- TersePrintPrefixToStrings(
- value, std::integral_constant<size_t, std::tuple_size<Tuple>::value>(),
- &result);
- return result;
-}
-
-} // namespace internal
-
-#if GTEST_HAS_ABSL
-namespace internal2 {
-template <typename T>
-void TypeWithoutFormatter<T, kConvertibleToStringView>::PrintValue(
- const T& value, ::std::ostream* os) {
- internal::PrintTo(absl::string_view(value), os);
-}
-} // namespace internal2
-#endif
-
-template <typename T>
-::std::string PrintToString(const T& value) {
- ::std::stringstream ss;
- internal::UniversalTersePrinter<T>::Print(value, &ss);
- return ss.str();
-}
-
-} // namespace testing
-
-// Include any custom printer added by the local installation.
-// We must include this header at the end to make sure it can use the
-// declarations from this file.
-#include "gtest/internal/custom/gtest-printers.h"
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Utilities for testing Google Test itself and code that uses Google Test
-// (e.g. frameworks built on top of Google Test).
-
-// GOOGLETEST_CM0004 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
-#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
-
-#include "gtest/gtest.h"
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-namespace testing {
-
-// This helper class can be used to mock out Google Test failure reporting
-// so that we can test Google Test or code that builds on Google Test.
-//
-// An object of this class appends a TestPartResult object to the
-// TestPartResultArray object given in the constructor whenever a Google Test
-// failure is reported. It can either intercept only failures that are
-// generated in the same thread that created this object or it can intercept
-// all generated failures. The scope of this mock object can be controlled with
-// the second argument to the two arguments constructor.
-class GTEST_API_ ScopedFakeTestPartResultReporter
- : public TestPartResultReporterInterface {
- public:
- // The two possible mocking modes of this object.
- enum InterceptMode {
- INTERCEPT_ONLY_CURRENT_THREAD, // Intercepts only thread local failures.
- INTERCEPT_ALL_THREADS // Intercepts all failures.
- };
-
- // The c'tor sets this object as the test part result reporter used
- // by Google Test. The 'result' parameter specifies where to report the
- // results. This reporter will only catch failures generated in the current
- // thread. DEPRECATED
- explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
-
- // Same as above, but you can choose the interception scope of this object.
- ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
- TestPartResultArray* result);
-
- // The d'tor restores the previous test part result reporter.
- ~ScopedFakeTestPartResultReporter() override;
-
- // Appends the TestPartResult object to the TestPartResultArray
- // received in the constructor.
- //
- // This method is from the TestPartResultReporterInterface
- // interface.
- void ReportTestPartResult(const TestPartResult& result) override;
-
- private:
- void Init();
-
- const InterceptMode intercept_mode_;
- TestPartResultReporterInterface* old_reporter_;
- TestPartResultArray* const result_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
-};
-
-namespace internal {
-
-// A helper class for implementing EXPECT_FATAL_FAILURE() and
-// EXPECT_NONFATAL_FAILURE(). Its destructor verifies that the given
-// TestPartResultArray contains exactly one failure that has the given
-// type and contains the given substring. If that's not the case, a
-// non-fatal failure will be generated.
-class GTEST_API_ SingleFailureChecker {
- public:
- // The constructor remembers the arguments.
- SingleFailureChecker(const TestPartResultArray* results,
- TestPartResult::Type type, const std::string& substr);
- ~SingleFailureChecker();
- private:
- const TestPartResultArray* const results_;
- const TestPartResult::Type type_;
- const std::string substr_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
-};
-
-} // namespace internal
-
-} // namespace testing
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-// A set of macros for testing Google Test assertions or code that's expected
-// to generate Google Test fatal failures. It verifies that the given
-// statement will cause exactly one fatal Google Test failure with 'substr'
-// being part of the failure message.
-//
-// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
-// affects and considers failures generated in the current thread and
-// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
-//
-// The verification of the assertion is done correctly even when the statement
-// throws an exception or aborts the current function.
-//
-// Known restrictions:
-// - 'statement' cannot reference local non-static variables or
-// non-static members of the current object.
-// - 'statement' cannot return a value.
-// - You cannot stream a failure message to this macro.
-//
-// Note that even though the implementations of the following two
-// macros are much alike, we cannot refactor them to use a common
-// helper macro, due to some peculiarity in how the preprocessor
-// works. The AcceptsMacroThatExpandsToUnprotectedComma test in
-// gtest_unittest.cc will fail to compile if we do that.
-#define EXPECT_FATAL_FAILURE(statement, substr) \
- do { \
- class GTestExpectFatalFailureHelper {\
- public:\
- static void Execute() { statement; }\
- };\
- ::testing::TestPartResultArray gtest_failures;\
- ::testing::internal::SingleFailureChecker gtest_checker(\
- >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
- {\
- ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
- ::testing::ScopedFakeTestPartResultReporter:: \
- INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
- GTestExpectFatalFailureHelper::Execute();\
- }\
- } while (::testing::internal::AlwaysFalse())
-
-#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
- do { \
- class GTestExpectFatalFailureHelper {\
- public:\
- static void Execute() { statement; }\
- };\
- ::testing::TestPartResultArray gtest_failures;\
- ::testing::internal::SingleFailureChecker gtest_checker(\
- >est_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
- {\
- ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
- ::testing::ScopedFakeTestPartResultReporter:: \
- INTERCEPT_ALL_THREADS, >est_failures);\
- GTestExpectFatalFailureHelper::Execute();\
- }\
- } while (::testing::internal::AlwaysFalse())
-
-// A macro for testing Google Test assertions or code that's expected to
-// generate Google Test non-fatal failures. It asserts that the given
-// statement will cause exactly one non-fatal Google Test failure with 'substr'
-// being part of the failure message.
-//
-// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
-// affects and considers failures generated in the current thread and
-// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
-//
-// 'statement' is allowed to reference local variables and members of
-// the current object.
-//
-// The verification of the assertion is done correctly even when the statement
-// throws an exception or aborts the current function.
-//
-// Known restrictions:
-// - You cannot stream a failure message to this macro.
-//
-// Note that even though the implementations of the following two
-// macros are much alike, we cannot refactor them to use a common
-// helper macro, due to some peculiarity in how the preprocessor
-// works. If we do that, the code won't compile when the user gives
-// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
-// expands to code containing an unprotected comma. The
-// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
-// catches that.
-//
-// For the same reason, we have to write
-// if (::testing::internal::AlwaysTrue()) { statement; }
-// instead of
-// GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
-// to avoid an MSVC warning on unreachable code.
-#define EXPECT_NONFATAL_FAILURE(statement, substr) \
- do {\
- ::testing::TestPartResultArray gtest_failures;\
- ::testing::internal::SingleFailureChecker gtest_checker(\
- >est_failures, ::testing::TestPartResult::kNonFatalFailure, \
- (substr));\
- {\
- ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
- ::testing::ScopedFakeTestPartResultReporter:: \
- INTERCEPT_ONLY_CURRENT_THREAD, >est_failures);\
- if (::testing::internal::AlwaysTrue()) { statement; }\
- }\
- } while (::testing::internal::AlwaysFalse())
-
-#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
- do {\
- ::testing::TestPartResultArray gtest_failures;\
- ::testing::internal::SingleFailureChecker gtest_checker(\
- >est_failures, ::testing::TestPartResult::kNonFatalFailure, \
- (substr));\
- {\
- ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
- ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
- >est_failures);\
- if (::testing::internal::AlwaysTrue()) { statement; }\
- }\
- } while (::testing::internal::AlwaysFalse())
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
-#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
-
-#include <iosfwd>
-#include <vector>
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-string.h"
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-namespace testing {
-
-// A copyable object representing the result of a test part (i.e. an
-// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
-//
-// Don't inherit from TestPartResult as its destructor is not virtual.
-class GTEST_API_ TestPartResult {
- public:
- // The possible outcomes of a test part (i.e. an assertion or an
- // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
- enum Type {
- kSuccess, // Succeeded.
- kNonFatalFailure, // Failed but the test can continue.
- kFatalFailure, // Failed and the test should be terminated.
- kSkip // Skipped.
- };
-
- // C'tor. TestPartResult does NOT have a default constructor.
- // Always use this constructor (with parameters) to create a
- // TestPartResult object.
- TestPartResult(Type a_type, const char* a_file_name, int a_line_number,
- const char* a_message)
- : type_(a_type),
- file_name_(a_file_name == nullptr ? "" : a_file_name),
- line_number_(a_line_number),
- summary_(ExtractSummary(a_message)),
- message_(a_message) {}
-
- // Gets the outcome of the test part.
- Type type() const { return type_; }
-
- // Gets the name of the source file where the test part took place, or
- // NULL if it's unknown.
- const char* file_name() const {
- return file_name_.empty() ? nullptr : file_name_.c_str();
- }
-
- // Gets the line in the source file where the test part took place,
- // or -1 if it's unknown.
- int line_number() const { return line_number_; }
-
- // Gets the summary of the failure message.
- const char* summary() const { return summary_.c_str(); }
-
- // Gets the message associated with the test part.
- const char* message() const { return message_.c_str(); }
-
- // Returns true if and only if the test part was skipped.
- bool skipped() const { return type_ == kSkip; }
-
- // Returns true if and only if the test part passed.
- bool passed() const { return type_ == kSuccess; }
-
- // Returns true if and only if the test part non-fatally failed.
- bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
-
- // Returns true if and only if the test part fatally failed.
- bool fatally_failed() const { return type_ == kFatalFailure; }
-
- // Returns true if and only if the test part failed.
- bool failed() const { return fatally_failed() || nonfatally_failed(); }
-
- private:
- Type type_;
-
- // Gets the summary of the failure message by omitting the stack
- // trace in it.
- static std::string ExtractSummary(const char* message);
-
- // The name of the source file where the test part took place, or
- // "" if the source file is unknown.
- std::string file_name_;
- // The line in the source file where the test part took place, or -1
- // if the line number is unknown.
- int line_number_;
- std::string summary_; // The test failure summary.
- std::string message_; // The test failure message.
-};
-
-// Prints a TestPartResult object.
-std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
-
-// An array of TestPartResult objects.
-//
-// Don't inherit from TestPartResultArray as its destructor is not
-// virtual.
-class GTEST_API_ TestPartResultArray {
- public:
- TestPartResultArray() {}
-
- // Appends the given TestPartResult to the array.
- void Append(const TestPartResult& result);
-
- // Returns the TestPartResult at the given index (0-based).
- const TestPartResult& GetTestPartResult(int index) const;
-
- // Returns the number of TestPartResult objects in the array.
- int size() const;
-
- private:
- std::vector<TestPartResult> array_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
-};
-
-// This interface knows how to report a test part result.
-class GTEST_API_ TestPartResultReporterInterface {
- public:
- virtual ~TestPartResultReporterInterface() {}
-
- virtual void ReportTestPartResult(const TestPartResult& result) = 0;
-};
-
-namespace internal {
-
-// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
-// statement generates new fatal failures. To do so it registers itself as the
-// current test part result reporter. Besides checking if fatal failures were
-// reported, it only delegates the reporting to the former result reporter.
-// The original result reporter is restored in the destructor.
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-class GTEST_API_ HasNewFatalFailureHelper
- : public TestPartResultReporterInterface {
- public:
- HasNewFatalFailureHelper();
- ~HasNewFatalFailureHelper() override;
- void ReportTestPartResult(const TestPartResult& result) override;
- bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
- private:
- bool has_new_fatal_failure_;
- TestPartResultReporterInterface* original_reporter_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
-};
-
-} // namespace internal
-
-} // namespace testing
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
-#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
-
-// This header implements typed tests and type-parameterized tests.
-
-// Typed (aka type-driven) tests repeat the same test for types in a
-// list. You must know which types you want to test with when writing
-// typed tests. Here's how you do it:
-
-#if 0
-
-// First, define a fixture class template. It should be parameterized
-// by a type. Remember to derive it from testing::Test.
-template <typename T>
-class FooTest : public testing::Test {
- public:
- ...
- typedef std::list<T> List;
- static T shared_;
- T value_;
-};
-
-// Next, associate a list of types with the test suite, which will be
-// repeated for each type in the list. The typedef is necessary for
-// the macro to parse correctly.
-typedef testing::Types<char, int, unsigned int> MyTypes;
-TYPED_TEST_SUITE(FooTest, MyTypes);
-
-// If the type list contains only one type, you can write that type
-// directly without Types<...>:
-// TYPED_TEST_SUITE(FooTest, int);
-
-// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
-// tests for this test suite as you want.
-TYPED_TEST(FooTest, DoesBlah) {
- // Inside a test, refer to the special name TypeParam to get the type
- // parameter. Since we are inside a derived class template, C++ requires
- // us to visit the members of FooTest via 'this'.
- TypeParam n = this->value_;
-
- // To visit static members of the fixture, add the TestFixture::
- // prefix.
- n += TestFixture::shared_;
-
- // To refer to typedefs in the fixture, add the "typename
- // TestFixture::" prefix.
- typename TestFixture::List values;
- values.push_back(n);
- ...
-}
-
-TYPED_TEST(FooTest, HasPropertyA) { ... }
-
-// TYPED_TEST_SUITE takes an optional third argument which allows to specify a
-// class that generates custom test name suffixes based on the type. This should
-// be a class which has a static template function GetName(int index) returning
-// a string for each type. The provided integer index equals the index of the
-// type in the provided type list. In many cases the index can be ignored.
-//
-// For example:
-// class MyTypeNames {
-// public:
-// template <typename T>
-// static std::string GetName(int) {
-// if (std::is_same<T, char>()) return "char";
-// if (std::is_same<T, int>()) return "int";
-// if (std::is_same<T, unsigned int>()) return "unsignedInt";
-// }
-// };
-// TYPED_TEST_SUITE(FooTest, MyTypes, MyTypeNames);
-
-#endif // 0
-
-// Type-parameterized tests are abstract test patterns parameterized
-// by a type. Compared with typed tests, type-parameterized tests
-// allow you to define the test pattern without knowing what the type
-// parameters are. The defined pattern can be instantiated with
-// different types any number of times, in any number of translation
-// units.
-//
-// If you are designing an interface or concept, you can define a
-// suite of type-parameterized tests to verify properties that any
-// valid implementation of the interface/concept should have. Then,
-// each implementation can easily instantiate the test suite to verify
-// that it conforms to the requirements, without having to write
-// similar tests repeatedly. Here's an example:
-
-#if 0
-
-// First, define a fixture class template. It should be parameterized
-// by a type. Remember to derive it from testing::Test.
-template <typename T>
-class FooTest : public testing::Test {
- ...
-};
-
-// Next, declare that you will define a type-parameterized test suite
-// (the _P suffix is for "parameterized" or "pattern", whichever you
-// prefer):
-TYPED_TEST_SUITE_P(FooTest);
-
-// Then, use TYPED_TEST_P() to define as many type-parameterized tests
-// for this type-parameterized test suite as you want.
-TYPED_TEST_P(FooTest, DoesBlah) {
- // Inside a test, refer to TypeParam to get the type parameter.
- TypeParam n = 0;
- ...
-}
-
-TYPED_TEST_P(FooTest, HasPropertyA) { ... }
-
-// Now the tricky part: you need to register all test patterns before
-// you can instantiate them. The first argument of the macro is the
-// test suite name; the rest are the names of the tests in this test
-// case.
-REGISTER_TYPED_TEST_SUITE_P(FooTest,
- DoesBlah, HasPropertyA);
-
-// Finally, you are free to instantiate the pattern with the types you
-// want. If you put the above code in a header file, you can #include
-// it in multiple C++ source files and instantiate it multiple times.
-//
-// To distinguish different instances of the pattern, the first
-// argument to the INSTANTIATE_* macro is a prefix that will be added
-// to the actual test suite name. Remember to pick unique prefixes for
-// different instances.
-typedef testing::Types<char, int, unsigned int> MyTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes);
-
-// If the type list contains only one type, you can write that type
-// directly without Types<...>:
-// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, int);
-//
-// Similar to the optional argument of TYPED_TEST_SUITE above,
-// INSTANTIATE_TEST_SUITE_P takes an optional fourth argument which allows to
-// generate custom names.
-// INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes, MyTypeNames);
-
-#endif // 0
-
-#include "gtest/internal/gtest-port.h"
-#include "gtest/internal/gtest-type-util.h"
-
-// Implements typed tests.
-
-#if GTEST_HAS_TYPED_TEST
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// Expands to the name of the typedef for the type parameters of the
-// given test suite.
-#define GTEST_TYPE_PARAMS_(TestSuiteName) gtest_type_params_##TestSuiteName##_
-
-// Expands to the name of the typedef for the NameGenerator, responsible for
-// creating the suffixes of the name.
-#define GTEST_NAME_GENERATOR_(TestSuiteName) \
- gtest_type_params_##TestSuiteName##_NameGenerator
-
-#define TYPED_TEST_SUITE(CaseName, Types, ...) \
- typedef ::testing::internal::TypeList<Types>::type GTEST_TYPE_PARAMS_( \
- CaseName); \
- typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \
- GTEST_NAME_GENERATOR_(CaseName)
-
-# define TYPED_TEST(CaseName, TestName) \
- template <typename gtest_TypeParam_> \
- class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
- : public CaseName<gtest_TypeParam_> { \
- private: \
- typedef CaseName<gtest_TypeParam_> TestFixture; \
- typedef gtest_TypeParam_ TypeParam; \
- virtual void TestBody(); \
- }; \
- static bool gtest_##CaseName##_##TestName##_registered_ \
- GTEST_ATTRIBUTE_UNUSED_ = \
- ::testing::internal::TypeParameterizedTest< \
- CaseName, \
- ::testing::internal::TemplateSel<GTEST_TEST_CLASS_NAME_(CaseName, \
- TestName)>, \
- GTEST_TYPE_PARAMS_( \
- CaseName)>::Register("", \
- ::testing::internal::CodeLocation( \
- __FILE__, __LINE__), \
- #CaseName, #TestName, 0, \
- ::testing::internal::GenerateNames< \
- GTEST_NAME_GENERATOR_(CaseName), \
- GTEST_TYPE_PARAMS_(CaseName)>()); \
- template <typename gtest_TypeParam_> \
- void GTEST_TEST_CLASS_NAME_(CaseName, \
- TestName)<gtest_TypeParam_>::TestBody()
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define TYPED_TEST_CASE \
- static_assert(::testing::internal::TypedTestCaseIsDeprecated(), ""); \
- TYPED_TEST_SUITE
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-#endif // GTEST_HAS_TYPED_TEST
-
-// Implements type-parameterized tests.
-
-#if GTEST_HAS_TYPED_TEST_P
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// Expands to the namespace name that the type-parameterized tests for
-// the given type-parameterized test suite are defined in. The exact
-// name of the namespace is subject to change without notice.
-#define GTEST_SUITE_NAMESPACE_(TestSuiteName) gtest_suite_##TestSuiteName##_
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// Expands to the name of the variable used to remember the names of
-// the defined tests in the given test suite.
-#define GTEST_TYPED_TEST_SUITE_P_STATE_(TestSuiteName) \
- gtest_typed_test_suite_p_state_##TestSuiteName##_
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
-//
-// Expands to the name of the variable used to remember the names of
-// the registered tests in the given test suite.
-#define GTEST_REGISTERED_TEST_NAMES_(TestSuiteName) \
- gtest_registered_test_names_##TestSuiteName##_
-
-// The variables defined in the type-parameterized test macros are
-// static as typically these macros are used in a .h file that can be
-// #included in multiple translation units linked together.
-#define TYPED_TEST_SUITE_P(SuiteName) \
- static ::testing::internal::TypedTestSuitePState \
- GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName)
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define TYPED_TEST_CASE_P \
- static_assert(::testing::internal::TypedTestCase_P_IsDeprecated(), ""); \
- TYPED_TEST_SUITE_P
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-#define TYPED_TEST_P(SuiteName, TestName) \
- namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
- template <typename gtest_TypeParam_> \
- class TestName : public SuiteName<gtest_TypeParam_> { \
- private: \
- typedef SuiteName<gtest_TypeParam_> TestFixture; \
- typedef gtest_TypeParam_ TypeParam; \
- virtual void TestBody(); \
- }; \
- static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
- GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \
- __FILE__, __LINE__, #SuiteName, #TestName); \
- } \
- template <typename gtest_TypeParam_> \
- void GTEST_SUITE_NAMESPACE_( \
- SuiteName)::TestName<gtest_TypeParam_>::TestBody()
-
-#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \
- namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \
- typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
- } \
- static const char* const GTEST_REGISTERED_TEST_NAMES_( \
- SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \
- GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \
- __FILE__, __LINE__, #__VA_ARGS__)
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define REGISTER_TYPED_TEST_CASE_P \
- static_assert(::testing::internal::RegisterTypedTestCase_P_IsDeprecated(), \
- ""); \
- REGISTER_TYPED_TEST_SUITE_P
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \
- static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \
- ::testing::internal::TypeParameterizedTestSuite< \
- SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \
- ::testing::internal::TypeList<Types>::type>:: \
- Register(#Prefix, \
- ::testing::internal::CodeLocation(__FILE__, __LINE__), \
- >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \
- GTEST_REGISTERED_TEST_NAMES_(SuiteName), \
- ::testing::internal::GenerateNames< \
- ::testing::internal::NameGeneratorSelector< \
- __VA_ARGS__>::type, \
- ::testing::internal::TypeList<Types>::type>())
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-#define INSTANTIATE_TYPED_TEST_CASE_P \
- static_assert( \
- ::testing::internal::InstantiateTypedTestCase_P_IsDeprecated(), ""); \
- INSTANTIATE_TYPED_TEST_SUITE_P
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-#endif // GTEST_HAS_TYPED_TEST_P
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file defines the public API for Google Test. It should be
-// included by any test program that uses Google Test.
-//
-// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
-// leave some internal implementation details in this header file.
-// They are clearly marked by comments like this:
-//
-// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-//
-// Such code is NOT meant to be used by a user directly, and is subject
-// to CHANGE WITHOUT NOTICE. Therefore DO NOT DEPEND ON IT in a user
-// program!
-//
-// Acknowledgment: Google Test borrowed the idea of automatic test
-// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
-// easyUnit framework.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
-#define GTEST_INCLUDE_GTEST_GTEST_H_
-
-#include <cstddef>
-#include <limits>
-#include <memory>
-#include <ostream>
-#include <type_traits>
-#include <vector>
-
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-string.h"
-#include "gtest/gtest-death-test.h"
-#include "gtest/gtest-matchers.h"
-#include "gtest/gtest-message.h"
-#include "gtest/gtest-param-test.h"
-#include "gtest/gtest-printers.h"
-#include "gtest/gtest_prod.h"
-#include "gtest/gtest-test-part.h"
-#include "gtest/gtest-typed-test.h"
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-namespace testing {
-
-// Silence C4100 (unreferenced formal parameter) and 4805
-// unsafe mix of type 'const int' and type 'const bool'
-#ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable:4805)
-# pragma warning(disable:4100)
-#endif
-
-
-// Declares the flags.
-
-// This flag temporary enables the disabled tests.
-GTEST_DECLARE_bool_(also_run_disabled_tests);
-
-// This flag brings the debugger on an assertion failure.
-GTEST_DECLARE_bool_(break_on_failure);
-
-// This flag controls whether Google Test catches all test-thrown exceptions
-// and logs them as failures.
-GTEST_DECLARE_bool_(catch_exceptions);
-
-// This flag enables using colors in terminal output. Available values are
-// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
-// to let Google Test decide.
-GTEST_DECLARE_string_(color);
-
-// This flag sets up the filter to select by name using a glob pattern
-// the tests to run. If the filter is not given all tests are executed.
-GTEST_DECLARE_string_(filter);
-
-// This flag controls whether Google Test installs a signal handler that dumps
-// debugging information when fatal signals are raised.
-GTEST_DECLARE_bool_(install_failure_signal_handler);
-
-// This flag causes the Google Test to list tests. None of the tests listed
-// are actually run if the flag is provided.
-GTEST_DECLARE_bool_(list_tests);
-
-// This flag controls whether Google Test emits a detailed XML report to a file
-// in addition to its normal textual output.
-GTEST_DECLARE_string_(output);
-
-// This flags control whether Google Test prints the elapsed time for each
-// test.
-GTEST_DECLARE_bool_(print_time);
-
-// This flags control whether Google Test prints UTF8 characters as text.
-GTEST_DECLARE_bool_(print_utf8);
-
-// This flag specifies the random number seed.
-GTEST_DECLARE_int32_(random_seed);
-
-// This flag sets how many times the tests are repeated. The default value
-// is 1. If the value is -1 the tests are repeating forever.
-GTEST_DECLARE_int32_(repeat);
-
-// This flag controls whether Google Test includes Google Test internal
-// stack frames in failure stack traces.
-GTEST_DECLARE_bool_(show_internal_stack_frames);
-
-// When this flag is specified, tests' order is randomized on every iteration.
-GTEST_DECLARE_bool_(shuffle);
-
-// This flag specifies the maximum number of stack frames to be
-// printed in a failure message.
-GTEST_DECLARE_int32_(stack_trace_depth);
-
-// When this flag is specified, a failed assertion will throw an
-// exception if exceptions are enabled, or exit the program with a
-// non-zero code otherwise. For use with an external test framework.
-GTEST_DECLARE_bool_(throw_on_failure);
-
-// When this flag is set with a "host:port" string, on supported
-// platforms test results are streamed to the specified port on
-// the specified host machine.
-GTEST_DECLARE_string_(stream_result_to);
-
-#if GTEST_USE_OWN_FLAGFILE_FLAG_
-GTEST_DECLARE_string_(flagfile);
-#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
-
-// The upper limit for valid stack trace depths.
-const int kMaxStackTraceDepth = 100;
-
-namespace internal {
-
-class AssertHelper;
-class DefaultGlobalTestPartResultReporter;
-class ExecDeathTest;
-class NoExecDeathTest;
-class FinalSuccessChecker;
-class GTestFlagSaver;
-class StreamingListenerTest;
-class TestResultAccessor;
-class TestEventListenersAccessor;
-class TestEventRepeater;
-class UnitTestRecordPropertyTestHelper;
-class WindowsDeathTest;
-class FuchsiaDeathTest;
-class UnitTestImpl* GetUnitTestImpl();
-void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
- const std::string& message);
-
-} // namespace internal
-
-// The friend relationship of some of these classes is cyclic.
-// If we don't forward declare them the compiler might confuse the classes
-// in friendship clauses with same named classes on the scope.
-class Test;
-class TestSuite;
-
-// Old API is still available but deprecated
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-using TestCase = TestSuite;
-#endif
-class TestInfo;
-class UnitTest;
-
-// A class for indicating whether an assertion was successful. When
-// the assertion wasn't successful, the AssertionResult object
-// remembers a non-empty message that describes how it failed.
-//
-// To create an instance of this class, use one of the factory functions
-// (AssertionSuccess() and AssertionFailure()).
-//
-// This class is useful for two purposes:
-// 1. Defining predicate functions to be used with Boolean test assertions
-// EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
-// 2. Defining predicate-format functions to be
-// used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
-//
-// For example, if you define IsEven predicate:
-//
-// testing::AssertionResult IsEven(int n) {
-// if ((n % 2) == 0)
-// return testing::AssertionSuccess();
-// else
-// return testing::AssertionFailure() << n << " is odd";
-// }
-//
-// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
-// will print the message
-//
-// Value of: IsEven(Fib(5))
-// Actual: false (5 is odd)
-// Expected: true
-//
-// instead of a more opaque
-//
-// Value of: IsEven(Fib(5))
-// Actual: false
-// Expected: true
-//
-// in case IsEven is a simple Boolean predicate.
-//
-// If you expect your predicate to be reused and want to support informative
-// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
-// about half as often as positive ones in our tests), supply messages for
-// both success and failure cases:
-//
-// testing::AssertionResult IsEven(int n) {
-// if ((n % 2) == 0)
-// return testing::AssertionSuccess() << n << " is even";
-// else
-// return testing::AssertionFailure() << n << " is odd";
-// }
-//
-// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
-//
-// Value of: IsEven(Fib(6))
-// Actual: true (8 is even)
-// Expected: false
-//
-// NB: Predicates that support negative Boolean assertions have reduced
-// performance in positive ones so be careful not to use them in tests
-// that have lots (tens of thousands) of positive Boolean assertions.
-//
-// To use this class with EXPECT_PRED_FORMAT assertions such as:
-//
-// // Verifies that Foo() returns an even number.
-// EXPECT_PRED_FORMAT1(IsEven, Foo());
-//
-// you need to define:
-//
-// testing::AssertionResult IsEven(const char* expr, int n) {
-// if ((n % 2) == 0)
-// return testing::AssertionSuccess();
-// else
-// return testing::AssertionFailure()
-// << "Expected: " << expr << " is even\n Actual: it's " << n;
-// }
-//
-// If Foo() returns 5, you will see the following message:
-//
-// Expected: Foo() is even
-// Actual: it's 5
-//
-class GTEST_API_ AssertionResult {
- public:
- // Copy constructor.
- // Used in EXPECT_TRUE/FALSE(assertion_result).
- AssertionResult(const AssertionResult& other);
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
-#endif
-
- // Used in the EXPECT_TRUE/FALSE(bool_expression).
- //
- // T must be contextually convertible to bool.
- //
- // The second parameter prevents this overload from being considered if
- // the argument is implicitly convertible to AssertionResult. In that case
- // we want AssertionResult's copy constructor to be used.
- template <typename T>
- explicit AssertionResult(
- const T& success,
- typename std::enable_if<
- !std::is_convertible<T, AssertionResult>::value>::type*
- /*enabler*/
- = nullptr)
- : success_(success) {}
-
-#if defined(_MSC_VER) && _MSC_VER < 1910
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-#endif
-
- // Assignment operator.
- AssertionResult& operator=(AssertionResult other) {
- swap(other);
- return *this;
- }
-
- // Returns true if and only if the assertion succeeded.
- operator bool() const { return success_; } // NOLINT
-
- // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
- AssertionResult operator!() const;
-
- // Returns the text streamed into this AssertionResult. Test assertions
- // use it when they fail (i.e., the predicate's outcome doesn't match the
- // assertion's expectation). When nothing has been streamed into the
- // object, returns an empty string.
- const char* message() const {
- return message_.get() != nullptr ? message_->c_str() : "";
- }
- // Deprecated; please use message() instead.
- const char* failure_message() const { return message(); }
-
- // Streams a custom failure message into this object.
- template <typename T> AssertionResult& operator<<(const T& value) {
- AppendMessage(Message() << value);
- return *this;
- }
-
- // Allows streaming basic output manipulators such as endl or flush into
- // this object.
- AssertionResult& operator<<(
- ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
- AppendMessage(Message() << basic_manipulator);
- return *this;
- }
-
- private:
- // Appends the contents of message to message_.
- void AppendMessage(const Message& a_message) {
- if (message_.get() == nullptr) message_.reset(new ::std::string);
- message_->append(a_message.GetString().c_str());
- }
-
- // Swap the contents of this AssertionResult with other.
- void swap(AssertionResult& other);
-
- // Stores result of the assertion predicate.
- bool success_;
- // Stores the message describing the condition in case the expectation
- // construct is not satisfied with the predicate's outcome.
- // Referenced via a pointer to avoid taking too much stack frame space
- // with test assertions.
- std::unique_ptr< ::std::string> message_;
-};
-
-// Makes a successful assertion result.
-GTEST_API_ AssertionResult AssertionSuccess();
-
-// Makes a failed assertion result.
-GTEST_API_ AssertionResult AssertionFailure();
-
-// Makes a failed assertion result with the given failure message.
-// Deprecated; use AssertionFailure() << msg.
-GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
-
-} // namespace testing
-
-// Includes the auto-generated header that implements a family of generic
-// predicate assertion macros. This include comes late because it relies on
-// APIs declared above.
-#include "gtest/gtest_pred_impl.h"
-
-namespace testing {
-
-// The abstract class that all tests inherit from.
-//
-// In Google Test, a unit test program contains one or many TestSuites, and
-// each TestSuite contains one or many Tests.
-//
-// When you define a test using the TEST macro, you don't need to
-// explicitly derive from Test - the TEST macro automatically does
-// this for you.
-//
-// The only time you derive from Test is when defining a test fixture
-// to be used in a TEST_F. For example:
-//
-// class FooTest : public testing::Test {
-// protected:
-// void SetUp() override { ... }
-// void TearDown() override { ... }
-// ...
-// };
-//
-// TEST_F(FooTest, Bar) { ... }
-// TEST_F(FooTest, Baz) { ... }
-//
-// Test is not copyable.
-class GTEST_API_ Test {
- public:
- friend class TestInfo;
-
- // The d'tor is virtual as we intend to inherit from Test.
- virtual ~Test();
-
- // Sets up the stuff shared by all tests in this test case.
- //
- // Google Test will call Foo::SetUpTestSuite() before running the first
- // test in test case Foo. Hence a sub-class can define its own
- // SetUpTestSuite() method to shadow the one defined in the super
- // class.
- // Failures that happen during SetUpTestSuite are logged but otherwise
- // ignored.
- static void SetUpTestSuite() {}
-
- // Tears down the stuff shared by all tests in this test suite.
- //
- // Google Test will call Foo::TearDownTestSuite() after running the last
- // test in test case Foo. Hence a sub-class can define its own
- // TearDownTestSuite() method to shadow the one defined in the super
- // class.
- // Failures that happen during TearDownTestSuite are logged but otherwise
- // ignored.
- static void TearDownTestSuite() {}
-
- // Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- static void TearDownTestCase() {}
- static void SetUpTestCase() {}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Returns true if and only if the current test has a fatal failure.
- static bool HasFatalFailure();
-
- // Returns true if and only if the current test has a non-fatal failure.
- static bool HasNonfatalFailure();
-
- // Returns true if and only if the current test was skipped.
- static bool IsSkipped();
-
- // Returns true if and only if the current test has a (either fatal or
- // non-fatal) failure.
- static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
-
- // Logs a property for the current test, test suite, or for the entire
- // invocation of the test program when used outside of the context of a
- // test suite. Only the last value for a given key is remembered. These
- // are public static so they can be called from utility functions that are
- // not members of the test fixture. Calls to RecordProperty made during
- // lifespan of the test (from the moment its constructor starts to the
- // moment its destructor finishes) will be output in XML as attributes of
- // the <testcase> element. Properties recorded from fixture's
- // SetUpTestSuite or TearDownTestSuite are logged as attributes of the
- // corresponding <testsuite> element. Calls to RecordProperty made in the
- // global context (before or after invocation of RUN_ALL_TESTS and from
- // SetUp/TearDown method of Environment objects registered with Google
- // Test) will be output as attributes of the <testsuites> element.
- static void RecordProperty(const std::string& key, const std::string& value);
- static void RecordProperty(const std::string& key, int value);
-
- protected:
- // Creates a Test object.
- Test();
-
- // Sets up the test fixture.
- virtual void SetUp();
-
- // Tears down the test fixture.
- virtual void TearDown();
-
- private:
- // Returns true if and only if the current test has the same fixture class
- // as the first test in the current test suite.
- static bool HasSameFixtureClass();
-
- // Runs the test after the test fixture has been set up.
- //
- // A sub-class must implement this to define the test logic.
- //
- // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
- // Instead, use the TEST or TEST_F macro.
- virtual void TestBody() = 0;
-
- // Sets up, executes, and tears down the test.
- void Run();
-
- // Deletes self. We deliberately pick an unusual name for this
- // internal method to avoid clashing with names used in user TESTs.
- void DeleteSelf_() { delete this; }
-
- const std::unique_ptr<GTEST_FLAG_SAVER_> gtest_flag_saver_;
-
- // Often a user misspells SetUp() as Setup() and spends a long time
- // wondering why it is never called by Google Test. The declaration of
- // the following method is solely for catching such an error at
- // compile time:
- //
- // - The return type is deliberately chosen to be not void, so it
- // will be a conflict if void Setup() is declared in the user's
- // test fixture.
- //
- // - This method is private, so it will be another compiler error
- // if the method is called from the user's test fixture.
- //
- // DO NOT OVERRIDE THIS FUNCTION.
- //
- // If you see an error about overriding the following function or
- // about it being private, you have mis-spelled SetUp() as Setup().
- struct Setup_should_be_spelled_SetUp {};
- virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
-
- // We disallow copying Tests.
- GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
-};
-
-typedef internal::TimeInMillis TimeInMillis;
-
-// A copyable object representing a user specified test property which can be
-// output as a key/value string pair.
-//
-// Don't inherit from TestProperty as its destructor is not virtual.
-class TestProperty {
- public:
- // C'tor. TestProperty does NOT have a default constructor.
- // Always use this constructor (with parameters) to create a
- // TestProperty object.
- TestProperty(const std::string& a_key, const std::string& a_value) :
- key_(a_key), value_(a_value) {
- }
-
- // Gets the user supplied key.
- const char* key() const {
- return key_.c_str();
- }
-
- // Gets the user supplied value.
- const char* value() const {
- return value_.c_str();
- }
-
- // Sets a new value, overriding the one supplied in the constructor.
- void SetValue(const std::string& new_value) {
- value_ = new_value;
- }
-
- private:
- // The key supplied by the user.
- std::string key_;
- // The value supplied by the user.
- std::string value_;
-};
-
-// The result of a single Test. This includes a list of
-// TestPartResults, a list of TestProperties, a count of how many
-// death tests there are in the Test, and how much time it took to run
-// the Test.
-//
-// TestResult is not copyable.
-class GTEST_API_ TestResult {
- public:
- // Creates an empty TestResult.
- TestResult();
-
- // D'tor. Do not inherit from TestResult.
- ~TestResult();
-
- // Gets the number of all test parts. This is the sum of the number
- // of successful test parts and the number of failed test parts.
- int total_part_count() const;
-
- // Returns the number of the test properties.
- int test_property_count() const;
-
- // Returns true if and only if the test passed (i.e. no test part failed).
- bool Passed() const { return !Skipped() && !Failed(); }
-
- // Returns true if and only if the test was skipped.
- bool Skipped() const;
-
- // Returns true if and only if the test failed.
- bool Failed() const;
-
- // Returns true if and only if the test fatally failed.
- bool HasFatalFailure() const;
-
- // Returns true if and only if the test has a non-fatal failure.
- bool HasNonfatalFailure() const;
-
- // Returns the elapsed time, in milliseconds.
- TimeInMillis elapsed_time() const { return elapsed_time_; }
-
- // Gets the time of the test case start, in ms from the start of the
- // UNIX epoch.
- TimeInMillis start_timestamp() const { return start_timestamp_; }
-
- // Returns the i-th test part result among all the results. i can range from 0
- // to total_part_count() - 1. If i is not in that range, aborts the program.
- const TestPartResult& GetTestPartResult(int i) const;
-
- // Returns the i-th test property. i can range from 0 to
- // test_property_count() - 1. If i is not in that range, aborts the
- // program.
- const TestProperty& GetTestProperty(int i) const;
-
- private:
- friend class TestInfo;
- friend class TestSuite;
- friend class UnitTest;
- friend class internal::DefaultGlobalTestPartResultReporter;
- friend class internal::ExecDeathTest;
- friend class internal::TestResultAccessor;
- friend class internal::UnitTestImpl;
- friend class internal::WindowsDeathTest;
- friend class internal::FuchsiaDeathTest;
-
- // Gets the vector of TestPartResults.
- const std::vector<TestPartResult>& test_part_results() const {
- return test_part_results_;
- }
-
- // Gets the vector of TestProperties.
- const std::vector<TestProperty>& test_properties() const {
- return test_properties_;
- }
-
- // Sets the start time.
- void set_start_timestamp(TimeInMillis start) { start_timestamp_ = start; }
-
- // Sets the elapsed time.
- void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
-
- // Adds a test property to the list. The property is validated and may add
- // a non-fatal failure if invalid (e.g., if it conflicts with reserved
- // key names). If a property is already recorded for the same key, the
- // value will be updated, rather than storing multiple values for the same
- // key. xml_element specifies the element for which the property is being
- // recorded and is used for validation.
- void RecordProperty(const std::string& xml_element,
- const TestProperty& test_property);
-
- // Adds a failure if the key is a reserved attribute of Google Test
- // testsuite tags. Returns true if the property is valid.
- // FIXME: Validate attribute names are legal and human readable.
- static bool ValidateTestProperty(const std::string& xml_element,
- const TestProperty& test_property);
-
- // Adds a test part result to the list.
- void AddTestPartResult(const TestPartResult& test_part_result);
-
- // Returns the death test count.
- int death_test_count() const { return death_test_count_; }
-
- // Increments the death test count, returning the new count.
- int increment_death_test_count() { return ++death_test_count_; }
-
- // Clears the test part results.
- void ClearTestPartResults();
-
- // Clears the object.
- void Clear();
-
- // Protects mutable state of the property vector and of owned
- // properties, whose values may be updated.
- internal::Mutex test_properites_mutex_;
-
- // The vector of TestPartResults
- std::vector<TestPartResult> test_part_results_;
- // The vector of TestProperties
- std::vector<TestProperty> test_properties_;
- // Running count of death tests.
- int death_test_count_;
- // The start time, in milliseconds since UNIX Epoch.
- TimeInMillis start_timestamp_;
- // The elapsed time, in milliseconds.
- TimeInMillis elapsed_time_;
-
- // We disallow copying TestResult.
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
-}; // class TestResult
-
-// A TestInfo object stores the following information about a test:
-//
-// Test suite name
-// Test name
-// Whether the test should be run
-// A function pointer that creates the test object when invoked
-// Test result
-//
-// The constructor of TestInfo registers itself with the UnitTest
-// singleton such that the RUN_ALL_TESTS() macro knows which tests to
-// run.
-class GTEST_API_ TestInfo {
- public:
- // Destructs a TestInfo object. This function is not virtual, so
- // don't inherit from TestInfo.
- ~TestInfo();
-
- // Returns the test suite name.
- const char* test_suite_name() const { return test_suite_name_.c_str(); }
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- const char* test_case_name() const { return test_suite_name(); }
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Returns the test name.
- const char* name() const { return name_.c_str(); }
-
- // Returns the name of the parameter type, or NULL if this is not a typed
- // or a type-parameterized test.
- const char* type_param() const {
- if (type_param_.get() != nullptr) return type_param_->c_str();
- return nullptr;
- }
-
- // Returns the text representation of the value parameter, or NULL if this
- // is not a value-parameterized test.
- const char* value_param() const {
- if (value_param_.get() != nullptr) return value_param_->c_str();
- return nullptr;
- }
-
- // Returns the file name where this test is defined.
- const char* file() const { return location_.file.c_str(); }
-
- // Returns the line where this test is defined.
- int line() const { return location_.line; }
-
- // Return true if this test should not be run because it's in another shard.
- bool is_in_another_shard() const { return is_in_another_shard_; }
-
- // Returns true if this test should run, that is if the test is not
- // disabled (or it is disabled but the also_run_disabled_tests flag has
- // been specified) and its full name matches the user-specified filter.
- //
- // Google Test allows the user to filter the tests by their full names.
- // The full name of a test Bar in test suite Foo is defined as
- // "Foo.Bar". Only the tests that match the filter will run.
- //
- // A filter is a colon-separated list of glob (not regex) patterns,
- // optionally followed by a '-' and a colon-separated list of
- // negative patterns (tests to exclude). A test is run if it
- // matches one of the positive patterns and does not match any of
- // the negative patterns.
- //
- // For example, *A*:Foo.* is a filter that matches any string that
- // contains the character 'A' or starts with "Foo.".
- bool should_run() const { return should_run_; }
-
- // Returns true if and only if this test will appear in the XML report.
- bool is_reportable() const {
- // The XML report includes tests matching the filter, excluding those
- // run in other shards.
- return matches_filter_ && !is_in_another_shard_;
- }
-
- // Returns the result of the test.
- const TestResult* result() const { return &result_; }
-
- private:
-#if GTEST_HAS_DEATH_TEST
- friend class internal::DefaultDeathTestFactory;
-#endif // GTEST_HAS_DEATH_TEST
- friend class Test;
- friend class TestSuite;
- friend class internal::UnitTestImpl;
- friend class internal::StreamingListenerTest;
- friend TestInfo* internal::MakeAndRegisterTestInfo(
- const char* test_suite_name, const char* name, const char* type_param,
- const char* value_param, internal::CodeLocation code_location,
- internal::TypeId fixture_class_id, internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc,
- internal::TestFactoryBase* factory);
-
- // Constructs a TestInfo object. The newly constructed instance assumes
- // ownership of the factory object.
- TestInfo(const std::string& test_suite_name, const std::string& name,
- const char* a_type_param, // NULL if not a type-parameterized test
- const char* a_value_param, // NULL if not a value-parameterized test
- internal::CodeLocation a_code_location,
- internal::TypeId fixture_class_id,
- internal::TestFactoryBase* factory);
-
- // Increments the number of death tests encountered in this test so
- // far.
- int increment_death_test_count() {
- return result_.increment_death_test_count();
- }
-
- // Creates the test object, runs it, records its result, and then
- // deletes it.
- void Run();
-
- static void ClearTestResult(TestInfo* test_info) {
- test_info->result_.Clear();
- }
-
- // These fields are immutable properties of the test.
- const std::string test_suite_name_; // test suite name
- const std::string name_; // Test name
- // Name of the parameter type, or NULL if this is not a typed or a
- // type-parameterized test.
- const std::unique_ptr<const ::std::string> type_param_;
- // Text representation of the value parameter, or NULL if this is not a
- // value-parameterized test.
- const std::unique_ptr<const ::std::string> value_param_;
- internal::CodeLocation location_;
- const internal::TypeId fixture_class_id_; // ID of the test fixture class
- bool should_run_; // True if and only if this test should run
- bool is_disabled_; // True if and only if this test is disabled
- bool matches_filter_; // True if this test matches the
- // user-specified filter.
- bool is_in_another_shard_; // Will be run in another shard.
- internal::TestFactoryBase* const factory_; // The factory that creates
- // the test object
-
- // This field is mutable and needs to be reset before running the
- // test for the second time.
- TestResult result_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
-};
-
-// A test suite, which consists of a vector of TestInfos.
-//
-// TestSuite is not copyable.
-class GTEST_API_ TestSuite {
- public:
- // Creates a TestSuite with the given name.
- //
- // TestSuite does NOT have a default constructor. Always use this
- // constructor to create a TestSuite object.
- //
- // Arguments:
- //
- // name: name of the test suite
- // a_type_param: the name of the test's type parameter, or NULL if
- // this is not a type-parameterized test.
- // set_up_tc: pointer to the function that sets up the test suite
- // tear_down_tc: pointer to the function that tears down the test suite
- TestSuite(const char* name, const char* a_type_param,
- internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc);
-
- // Destructor of TestSuite.
- virtual ~TestSuite();
-
- // Gets the name of the TestSuite.
- const char* name() const { return name_.c_str(); }
-
- // Returns the name of the parameter type, or NULL if this is not a
- // type-parameterized test suite.
- const char* type_param() const {
- if (type_param_.get() != nullptr) return type_param_->c_str();
- return nullptr;
- }
-
- // Returns true if any test in this test suite should run.
- bool should_run() const { return should_run_; }
-
- // Gets the number of successful tests in this test suite.
- int successful_test_count() const;
-
- // Gets the number of skipped tests in this test suite.
- int skipped_test_count() const;
-
- // Gets the number of failed tests in this test suite.
- int failed_test_count() const;
-
- // Gets the number of disabled tests that will be reported in the XML report.
- int reportable_disabled_test_count() const;
-
- // Gets the number of disabled tests in this test suite.
- int disabled_test_count() const;
-
- // Gets the number of tests to be printed in the XML report.
- int reportable_test_count() const;
-
- // Get the number of tests in this test suite that should run.
- int test_to_run_count() const;
-
- // Gets the number of all tests in this test suite.
- int total_test_count() const;
-
- // Returns true if and only if the test suite passed.
- bool Passed() const { return !Failed(); }
-
- // Returns true if and only if the test suite failed.
- bool Failed() const { return failed_test_count() > 0; }
-
- // Returns the elapsed time, in milliseconds.
- TimeInMillis elapsed_time() const { return elapsed_time_; }
-
- // Gets the time of the test suite start, in ms from the start of the
- // UNIX epoch.
- TimeInMillis start_timestamp() const { return start_timestamp_; }
-
- // Returns the i-th test among all the tests. i can range from 0 to
- // total_test_count() - 1. If i is not in that range, returns NULL.
- const TestInfo* GetTestInfo(int i) const;
-
- // Returns the TestResult that holds test properties recorded during
- // execution of SetUpTestSuite and TearDownTestSuite.
- const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
-
- private:
- friend class Test;
- friend class internal::UnitTestImpl;
-
- // Gets the (mutable) vector of TestInfos in this TestSuite.
- std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
-
- // Gets the (immutable) vector of TestInfos in this TestSuite.
- const std::vector<TestInfo*>& test_info_list() const {
- return test_info_list_;
- }
-
- // Returns the i-th test among all the tests. i can range from 0 to
- // total_test_count() - 1. If i is not in that range, returns NULL.
- TestInfo* GetMutableTestInfo(int i);
-
- // Sets the should_run member.
- void set_should_run(bool should) { should_run_ = should; }
-
- // Adds a TestInfo to this test suite. Will delete the TestInfo upon
- // destruction of the TestSuite object.
- void AddTestInfo(TestInfo * test_info);
-
- // Clears the results of all tests in this test suite.
- void ClearResult();
-
- // Clears the results of all tests in the given test suite.
- static void ClearTestSuiteResult(TestSuite* test_suite) {
- test_suite->ClearResult();
- }
-
- // Runs every test in this TestSuite.
- void Run();
-
- // Runs SetUpTestSuite() for this TestSuite. This wrapper is needed
- // for catching exceptions thrown from SetUpTestSuite().
- void RunSetUpTestSuite() {
- if (set_up_tc_ != nullptr) {
- (*set_up_tc_)();
- }
- }
-
- // Runs TearDownTestSuite() for this TestSuite. This wrapper is
- // needed for catching exceptions thrown from TearDownTestSuite().
- void RunTearDownTestSuite() {
- if (tear_down_tc_ != nullptr) {
- (*tear_down_tc_)();
- }
- }
-
- // Returns true if and only if test passed.
- static bool TestPassed(const TestInfo* test_info) {
- return test_info->should_run() && test_info->result()->Passed();
- }
-
- // Returns true if and only if test skipped.
- static bool TestSkipped(const TestInfo* test_info) {
- return test_info->should_run() && test_info->result()->Skipped();
- }
-
- // Returns true if and only if test failed.
- static bool TestFailed(const TestInfo* test_info) {
- return test_info->should_run() && test_info->result()->Failed();
- }
-
- // Returns true if and only if the test is disabled and will be reported in
- // the XML report.
- static bool TestReportableDisabled(const TestInfo* test_info) {
- return test_info->is_reportable() && test_info->is_disabled_;
- }
-
- // Returns true if and only if test is disabled.
- static bool TestDisabled(const TestInfo* test_info) {
- return test_info->is_disabled_;
- }
-
- // Returns true if and only if this test will appear in the XML report.
- static bool TestReportable(const TestInfo* test_info) {
- return test_info->is_reportable();
- }
-
- // Returns true if the given test should run.
- static bool ShouldRunTest(const TestInfo* test_info) {
- return test_info->should_run();
- }
-
- // Shuffles the tests in this test suite.
- void ShuffleTests(internal::Random* random);
-
- // Restores the test order to before the first shuffle.
- void UnshuffleTests();
-
- // Name of the test suite.
- std::string name_;
- // Name of the parameter type, or NULL if this is not a typed or a
- // type-parameterized test.
- const std::unique_ptr<const ::std::string> type_param_;
- // The vector of TestInfos in their original order. It owns the
- // elements in the vector.
- std::vector<TestInfo*> test_info_list_;
- // Provides a level of indirection for the test list to allow easy
- // shuffling and restoring the test order. The i-th element in this
- // vector is the index of the i-th test in the shuffled test list.
- std::vector<int> test_indices_;
- // Pointer to the function that sets up the test suite.
- internal::SetUpTestSuiteFunc set_up_tc_;
- // Pointer to the function that tears down the test suite.
- internal::TearDownTestSuiteFunc tear_down_tc_;
- // True if and only if any test in this test suite should run.
- bool should_run_;
- // The start time, in milliseconds since UNIX Epoch.
- TimeInMillis start_timestamp_;
- // Elapsed time, in milliseconds.
- TimeInMillis elapsed_time_;
- // Holds test properties recorded during execution of SetUpTestSuite and
- // TearDownTestSuite.
- TestResult ad_hoc_test_result_;
-
- // We disallow copying TestSuites.
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestSuite);
-};
-
-// An Environment object is capable of setting up and tearing down an
-// environment. You should subclass this to define your own
-// environment(s).
-//
-// An Environment object does the set-up and tear-down in virtual
-// methods SetUp() and TearDown() instead of the constructor and the
-// destructor, as:
-//
-// 1. You cannot safely throw from a destructor. This is a problem
-// as in some cases Google Test is used where exceptions are enabled, and
-// we may want to implement ASSERT_* using exceptions where they are
-// available.
-// 2. You cannot use ASSERT_* directly in a constructor or
-// destructor.
-class Environment {
- public:
- // The d'tor is virtual as we need to subclass Environment.
- virtual ~Environment() {}
-
- // Override this to define how to set up the environment.
- virtual void SetUp() {}
-
- // Override this to define how to tear down the environment.
- virtual void TearDown() {}
- private:
- // If you see an error about overriding the following function or
- // about it being private, you have mis-spelled SetUp() as Setup().
- struct Setup_should_be_spelled_SetUp {};
- virtual Setup_should_be_spelled_SetUp* Setup() { return nullptr; }
-};
-
-#if GTEST_HAS_EXCEPTIONS
-
-// Exception which can be thrown from TestEventListener::OnTestPartResult.
-class GTEST_API_ AssertionException
- : public internal::GoogleTestFailureException {
- public:
- explicit AssertionException(const TestPartResult& result)
- : GoogleTestFailureException(result) {}
-};
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// The interface for tracing execution of tests. The methods are organized in
-// the order the corresponding events are fired.
-class TestEventListener {
- public:
- virtual ~TestEventListener() {}
-
- // Fired before any test activity starts.
- virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
-
- // Fired before each iteration of tests starts. There may be more than
- // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
- // index, starting from 0.
- virtual void OnTestIterationStart(const UnitTest& unit_test,
- int iteration) = 0;
-
- // Fired before environment set-up for each iteration of tests starts.
- virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
-
- // Fired after environment set-up for each iteration of tests ends.
- virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
-
- // Fired before the test suite starts.
- virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {}
-
- // Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Fired before the test starts.
- virtual void OnTestStart(const TestInfo& test_info) = 0;
-
- // Fired after a failed assertion or a SUCCEED() invocation.
- // If you want to throw an exception from this function to skip to the next
- // TEST, it must be AssertionException defined above, or inherited from it.
- virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
-
- // Fired after the test ends.
- virtual void OnTestEnd(const TestInfo& test_info) = 0;
-
- // Fired after the test suite ends.
- virtual void OnTestSuiteEnd(const TestSuite& /*test_suite*/) {}
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Fired before environment tear-down for each iteration of tests starts.
- virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
-
- // Fired after environment tear-down for each iteration of tests ends.
- virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
-
- // Fired after each iteration of tests finishes.
- virtual void OnTestIterationEnd(const UnitTest& unit_test,
- int iteration) = 0;
-
- // Fired after all test activities have ended.
- virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
-};
-
-// The convenience class for users who need to override just one or two
-// methods and are not concerned that a possible change to a signature of
-// the methods they override will not be caught during the build. For
-// comments about each method please see the definition of TestEventListener
-// above.
-class EmptyTestEventListener : public TestEventListener {
- public:
- void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
- void OnTestIterationStart(const UnitTest& /*unit_test*/,
- int /*iteration*/) override {}
- void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {}
- void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
- void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {}
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseStart(const TestCase& /*test_case*/) override {}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- void OnTestStart(const TestInfo& /*test_info*/) override {}
- void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {}
- void OnTestEnd(const TestInfo& /*test_info*/) override {}
- void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {}
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseEnd(const TestCase& /*test_case*/) override {}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {}
- void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
- void OnTestIterationEnd(const UnitTest& /*unit_test*/,
- int /*iteration*/) override {}
- void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
-};
-
-// TestEventListeners lets users add listeners to track events in Google Test.
-class GTEST_API_ TestEventListeners {
- public:
- TestEventListeners();
- ~TestEventListeners();
-
- // Appends an event listener to the end of the list. Google Test assumes
- // the ownership of the listener (i.e. it will delete the listener when
- // the test program finishes).
- void Append(TestEventListener* listener);
-
- // Removes the given event listener from the list and returns it. It then
- // becomes the caller's responsibility to delete the listener. Returns
- // NULL if the listener is not found in the list.
- TestEventListener* Release(TestEventListener* listener);
-
- // Returns the standard listener responsible for the default console
- // output. Can be removed from the listeners list to shut down default
- // console output. Note that removing this object from the listener list
- // with Release transfers its ownership to the caller and makes this
- // function return NULL the next time.
- TestEventListener* default_result_printer() const {
- return default_result_printer_;
- }
-
- // Returns the standard listener responsible for the default XML output
- // controlled by the --gtest_output=xml flag. Can be removed from the
- // listeners list by users who want to shut down the default XML output
- // controlled by this flag and substitute it with custom one. Note that
- // removing this object from the listener list with Release transfers its
- // ownership to the caller and makes this function return NULL the next
- // time.
- TestEventListener* default_xml_generator() const {
- return default_xml_generator_;
- }
-
- private:
- friend class TestSuite;
- friend class TestInfo;
- friend class internal::DefaultGlobalTestPartResultReporter;
- friend class internal::NoExecDeathTest;
- friend class internal::TestEventListenersAccessor;
- friend class internal::UnitTestImpl;
-
- // Returns repeater that broadcasts the TestEventListener events to all
- // subscribers.
- TestEventListener* repeater();
-
- // Sets the default_result_printer attribute to the provided listener.
- // The listener is also added to the listener list and previous
- // default_result_printer is removed from it and deleted. The listener can
- // also be NULL in which case it will not be added to the list. Does
- // nothing if the previous and the current listener objects are the same.
- void SetDefaultResultPrinter(TestEventListener* listener);
-
- // Sets the default_xml_generator attribute to the provided listener. The
- // listener is also added to the listener list and previous
- // default_xml_generator is removed from it and deleted. The listener can
- // also be NULL in which case it will not be added to the list. Does
- // nothing if the previous and the current listener objects are the same.
- void SetDefaultXmlGenerator(TestEventListener* listener);
-
- // Controls whether events will be forwarded by the repeater to the
- // listeners in the list.
- bool EventForwardingEnabled() const;
- void SuppressEventForwarding();
-
- // The actual list of listeners.
- internal::TestEventRepeater* repeater_;
- // Listener responsible for the standard result output.
- TestEventListener* default_result_printer_;
- // Listener responsible for the creation of the XML output file.
- TestEventListener* default_xml_generator_;
-
- // We disallow copying TestEventListeners.
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
-};
-
-// A UnitTest consists of a vector of TestSuites.
-//
-// This is a singleton class. The only instance of UnitTest is
-// created when UnitTest::GetInstance() is first called. This
-// instance is never deleted.
-//
-// UnitTest is not copyable.
-//
-// This class is thread-safe as long as the methods are called
-// according to their specification.
-class GTEST_API_ UnitTest {
- public:
- // Gets the singleton UnitTest object. The first time this method
- // is called, a UnitTest object is constructed and returned.
- // Consecutive calls will return the same object.
- static UnitTest* GetInstance();
-
- // Runs all tests in this UnitTest object and prints the result.
- // Returns 0 if successful, or 1 otherwise.
- //
- // This method can only be called from the main thread.
- //
- // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
- int Run() GTEST_MUST_USE_RESULT_;
-
- // Returns the working directory when the first TEST() or TEST_F()
- // was executed. The UnitTest object owns the string.
- const char* original_working_dir() const;
-
- // Returns the TestSuite object for the test that's currently running,
- // or NULL if no test is running.
- const TestSuite* current_test_suite() const GTEST_LOCK_EXCLUDED_(mutex_);
-
-// Legacy API is still available but deprecated
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- const TestCase* current_test_case() const GTEST_LOCK_EXCLUDED_(mutex_);
-#endif
-
- // Returns the TestInfo object for the test that's currently running,
- // or NULL if no test is running.
- const TestInfo* current_test_info() const
- GTEST_LOCK_EXCLUDED_(mutex_);
-
- // Returns the random seed used at the start of the current test run.
- int random_seed() const;
-
- // Returns the ParameterizedTestSuiteRegistry object used to keep track of
- // value-parameterized tests and instantiate and register them.
- //
- // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
- internal::ParameterizedTestSuiteRegistry& parameterized_test_registry()
- GTEST_LOCK_EXCLUDED_(mutex_);
-
- // Gets the number of successful test suites.
- int successful_test_suite_count() const;
-
- // Gets the number of failed test suites.
- int failed_test_suite_count() const;
-
- // Gets the number of all test suites.
- int total_test_suite_count() const;
-
- // Gets the number of all test suites that contain at least one test
- // that should run.
- int test_suite_to_run_count() const;
-
- // Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- int successful_test_case_count() const;
- int failed_test_case_count() const;
- int total_test_case_count() const;
- int test_case_to_run_count() const;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Gets the number of successful tests.
- int successful_test_count() const;
-
- // Gets the number of skipped tests.
- int skipped_test_count() const;
-
- // Gets the number of failed tests.
- int failed_test_count() const;
-
- // Gets the number of disabled tests that will be reported in the XML report.
- int reportable_disabled_test_count() const;
-
- // Gets the number of disabled tests.
- int disabled_test_count() const;
-
- // Gets the number of tests to be printed in the XML report.
- int reportable_test_count() const;
-
- // Gets the number of all tests.
- int total_test_count() const;
-
- // Gets the number of tests that should run.
- int test_to_run_count() const;
-
- // Gets the time of the test program start, in ms from the start of the
- // UNIX epoch.
- TimeInMillis start_timestamp() const;
-
- // Gets the elapsed time, in milliseconds.
- TimeInMillis elapsed_time() const;
-
- // Returns true if and only if the unit test passed (i.e. all test suites
- // passed).
- bool Passed() const;
-
- // Returns true if and only if the unit test failed (i.e. some test suite
- // failed or something outside of all tests failed).
- bool Failed() const;
-
- // Gets the i-th test suite among all the test suites. i can range from 0 to
- // total_test_suite_count() - 1. If i is not in that range, returns NULL.
- const TestSuite* GetTestSuite(int i) const;
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- const TestCase* GetTestCase(int i) const;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Returns the TestResult containing information on test failures and
- // properties logged outside of individual test suites.
- const TestResult& ad_hoc_test_result() const;
-
- // Returns the list of event listeners that can be used to track events
- // inside Google Test.
- TestEventListeners& listeners();
-
- private:
- // Registers and returns a global test environment. When a test
- // program is run, all global test environments will be set-up in
- // the order they were registered. After all tests in the program
- // have finished, all global test environments will be torn-down in
- // the *reverse* order they were registered.
- //
- // The UnitTest object takes ownership of the given environment.
- //
- // This method can only be called from the main thread.
- Environment* AddEnvironment(Environment* env);
-
- // Adds a TestPartResult to the current TestResult object. All
- // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
- // eventually call this to report their results. The user code
- // should use the assertion macros instead of calling this directly.
- void AddTestPartResult(TestPartResult::Type result_type,
- const char* file_name,
- int line_number,
- const std::string& message,
- const std::string& os_stack_trace)
- GTEST_LOCK_EXCLUDED_(mutex_);
-
- // Adds a TestProperty to the current TestResult object when invoked from
- // inside a test, to current TestSuite's ad_hoc_test_result_ when invoked
- // from SetUpTestSuite or TearDownTestSuite, or to the global property set
- // when invoked elsewhere. If the result already contains a property with
- // the same key, the value will be updated.
- void RecordProperty(const std::string& key, const std::string& value);
-
- // Gets the i-th test suite among all the test suites. i can range from 0 to
- // total_test_suite_count() - 1. If i is not in that range, returns NULL.
- TestSuite* GetMutableTestSuite(int i);
-
- // Accessors for the implementation object.
- internal::UnitTestImpl* impl() { return impl_; }
- const internal::UnitTestImpl* impl() const { return impl_; }
-
- // These classes and functions are friends as they need to access private
- // members of UnitTest.
- friend class ScopedTrace;
- friend class Test;
- friend class internal::AssertHelper;
- friend class internal::StreamingListenerTest;
- friend class internal::UnitTestRecordPropertyTestHelper;
- friend Environment* AddGlobalTestEnvironment(Environment* env);
- friend internal::UnitTestImpl* internal::GetUnitTestImpl();
- friend void internal::ReportFailureInUnknownLocation(
- TestPartResult::Type result_type,
- const std::string& message);
-
- // Creates an empty UnitTest.
- UnitTest();
-
- // D'tor
- virtual ~UnitTest();
-
- // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
- // Google Test trace stack.
- void PushGTestTrace(const internal::TraceInfo& trace)
- GTEST_LOCK_EXCLUDED_(mutex_);
-
- // Pops a trace from the per-thread Google Test trace stack.
- void PopGTestTrace()
- GTEST_LOCK_EXCLUDED_(mutex_);
-
- // Protects mutable state in *impl_. This is mutable as some const
- // methods need to lock it too.
- mutable internal::Mutex mutex_;
-
- // Opaque implementation object. This field is never changed once
- // the object is constructed. We don't mark it as const here, as
- // doing so will cause a warning in the constructor of UnitTest.
- // Mutable state in *impl_ is protected by mutex_.
- internal::UnitTestImpl* impl_;
-
- // We disallow copying UnitTest.
- GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
-};
-
-// A convenient wrapper for adding an environment for the test
-// program.
-//
-// You should call this before RUN_ALL_TESTS() is called, probably in
-// main(). If you use gtest_main, you need to call this before main()
-// starts for it to take effect. For example, you can define a global
-// variable like this:
-//
-// testing::Environment* const foo_env =
-// testing::AddGlobalTestEnvironment(new FooEnvironment);
-//
-// However, we strongly recommend you to write your own main() and
-// call AddGlobalTestEnvironment() there, as relying on initialization
-// of global variables makes the code harder to read and may cause
-// problems when you register multiple environments from different
-// translation units and the environments have dependencies among them
-// (remember that the compiler doesn't guarantee the order in which
-// global variables from different translation units are initialized).
-inline Environment* AddGlobalTestEnvironment(Environment* env) {
- return UnitTest::GetInstance()->AddEnvironment(env);
-}
-
-// Initializes Google Test. This must be called before calling
-// RUN_ALL_TESTS(). In particular, it parses a command line for the
-// flags that Google Test recognizes. Whenever a Google Test flag is
-// seen, it is removed from argv, and *argc is decremented.
-//
-// No value is returned. Instead, the Google Test flag variables are
-// updated.
-//
-// Calling the function for the second time has no user-visible effect.
-GTEST_API_ void InitGoogleTest(int* argc, char** argv);
-
-// This overloaded version can be used in Windows programs compiled in
-// UNICODE mode.
-GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
-
-// This overloaded version can be used on Arduino/embedded platforms where
-// there is no argc/argv.
-GTEST_API_ void InitGoogleTest();
-
-namespace internal {
-
-// Separate the error generating code from the code path to reduce the stack
-// frame size of CmpHelperEQ. This helps reduce the overhead of some sanitizers
-// when calling EXPECT_* in a tight loop.
-template <typename T1, typename T2>
-AssertionResult CmpHelperEQFailure(const char* lhs_expression,
- const char* rhs_expression,
- const T1& lhs, const T2& rhs) {
- return EqFailure(lhs_expression,
- rhs_expression,
- FormatForComparisonFailureMessage(lhs, rhs),
- FormatForComparisonFailureMessage(rhs, lhs),
- false);
-}
-
-// This block of code defines operator==/!=
-// to block lexical scope lookup.
-// It prevents using invalid operator==/!= defined at namespace scope.
-struct faketype {};
-inline bool operator==(faketype, faketype) { return true; }
-inline bool operator!=(faketype, faketype) { return false; }
-
-// The helper function for {ASSERT|EXPECT}_EQ.
-template <typename T1, typename T2>
-AssertionResult CmpHelperEQ(const char* lhs_expression,
- const char* rhs_expression,
- const T1& lhs,
- const T2& rhs) {
- if (lhs == rhs) {
- return AssertionSuccess();
- }
-
- return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs);
-}
-
-// With this overloaded version, we allow anonymous enums to be used
-// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
-// can be implicitly cast to BiggestInt.
-GTEST_API_ AssertionResult CmpHelperEQ(const char* lhs_expression,
- const char* rhs_expression,
- BiggestInt lhs,
- BiggestInt rhs);
-
-class EqHelper {
- public:
- // This templatized version is for the general case.
- template <
- typename T1, typename T2,
- // Disable this overload for cases where one argument is a pointer
- // and the other is the null pointer constant.
- typename std::enable_if<!std::is_integral<T1>::value ||
- !std::is_pointer<T2>::value>::type* = nullptr>
- static AssertionResult Compare(const char* lhs_expression,
- const char* rhs_expression, const T1& lhs,
- const T2& rhs) {
- return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
- }
-
- // With this overloaded version, we allow anonymous enums to be used
- // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
- // enums can be implicitly cast to BiggestInt.
- //
- // Even though its body looks the same as the above version, we
- // cannot merge the two, as it will make anonymous enums unhappy.
- static AssertionResult Compare(const char* lhs_expression,
- const char* rhs_expression,
- BiggestInt lhs,
- BiggestInt rhs) {
- return CmpHelperEQ(lhs_expression, rhs_expression, lhs, rhs);
- }
-
- template <typename T>
- static AssertionResult Compare(
- const char* lhs_expression, const char* rhs_expression,
- // Handle cases where '0' is used as a null pointer literal.
- std::nullptr_t /* lhs */, T* rhs) {
- // We already know that 'lhs' is a null pointer.
- return CmpHelperEQ(lhs_expression, rhs_expression, static_cast<T*>(nullptr),
- rhs);
- }
-};
-
-// Separate the error generating code from the code path to reduce the stack
-// frame size of CmpHelperOP. This helps reduce the overhead of some sanitizers
-// when calling EXPECT_OP in a tight loop.
-template <typename T1, typename T2>
-AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
- const T1& val1, const T2& val2,
- const char* op) {
- return AssertionFailure()
- << "Expected: (" << expr1 << ") " << op << " (" << expr2
- << "), actual: " << FormatForComparisonFailureMessage(val1, val2)
- << " vs " << FormatForComparisonFailureMessage(val2, val1);
-}
-
-// A macro for implementing the helper functions needed to implement
-// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste
-// of similar code.
-//
-// For each templatized helper function, we also define an overloaded
-// version for BiggestInt in order to reduce code bloat and allow
-// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
-// with gcc 4.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-
-#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
-template <typename T1, typename T2>\
-AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
- const T1& val1, const T2& val2) {\
- if (val1 op val2) {\
- return AssertionSuccess();\
- } else {\
- return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\
- }\
-}\
-GTEST_API_ AssertionResult CmpHelper##op_name(\
- const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-
-// Implements the helper function for {ASSERT|EXPECT}_NE
-GTEST_IMPL_CMP_HELPER_(NE, !=);
-// Implements the helper function for {ASSERT|EXPECT}_LE
-GTEST_IMPL_CMP_HELPER_(LE, <=);
-// Implements the helper function for {ASSERT|EXPECT}_LT
-GTEST_IMPL_CMP_HELPER_(LT, <);
-// Implements the helper function for {ASSERT|EXPECT}_GE
-GTEST_IMPL_CMP_HELPER_(GE, >=);
-// Implements the helper function for {ASSERT|EXPECT}_GT
-GTEST_IMPL_CMP_HELPER_(GT, >);
-
-#undef GTEST_IMPL_CMP_HELPER_
-
-// The helper function for {ASSERT|EXPECT}_STREQ.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
- const char* s2_expression,
- const char* s1,
- const char* s2);
-
-// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* s1_expression,
- const char* s2_expression,
- const char* s1,
- const char* s2);
-
-// The helper function for {ASSERT|EXPECT}_STRNE.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
- const char* s2_expression,
- const char* s1,
- const char* s2);
-
-// The helper function for {ASSERT|EXPECT}_STRCASENE.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
- const char* s2_expression,
- const char* s1,
- const char* s2);
-
-
-// Helper function for *_STREQ on wide strings.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult CmpHelperSTREQ(const char* s1_expression,
- const char* s2_expression,
- const wchar_t* s1,
- const wchar_t* s2);
-
-// Helper function for *_STRNE on wide strings.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
- const char* s2_expression,
- const wchar_t* s1,
- const wchar_t* s2);
-
-} // namespace internal
-
-// IsSubstring() and IsNotSubstring() are intended to be used as the
-// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
-// themselves. They check whether needle is a substring of haystack
-// (NULL is considered a substring of itself only), and return an
-// appropriate error message when they fail.
-//
-// The {needle,haystack}_expr arguments are the stringified
-// expressions that generated the two real arguments.
-GTEST_API_ AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const char* needle, const char* haystack);
-GTEST_API_ AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const wchar_t* needle, const wchar_t* haystack);
-GTEST_API_ AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const char* needle, const char* haystack);
-GTEST_API_ AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const wchar_t* needle, const wchar_t* haystack);
-GTEST_API_ AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::string& needle, const ::std::string& haystack);
-GTEST_API_ AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::string& needle, const ::std::string& haystack);
-
-#if GTEST_HAS_STD_WSTRING
-GTEST_API_ AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::wstring& needle, const ::std::wstring& haystack);
-GTEST_API_ AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::wstring& needle, const ::std::wstring& haystack);
-#endif // GTEST_HAS_STD_WSTRING
-
-namespace internal {
-
-// Helper template function for comparing floating-points.
-//
-// Template parameter:
-//
-// RawType: the raw floating-point type (either float or double)
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-template <typename RawType>
-AssertionResult CmpHelperFloatingPointEQ(const char* lhs_expression,
- const char* rhs_expression,
- RawType lhs_value,
- RawType rhs_value) {
- const FloatingPoint<RawType> lhs(lhs_value), rhs(rhs_value);
-
- if (lhs.AlmostEquals(rhs)) {
- return AssertionSuccess();
- }
-
- ::std::stringstream lhs_ss;
- lhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
- << lhs_value;
-
- ::std::stringstream rhs_ss;
- rhs_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
- << rhs_value;
-
- return EqFailure(lhs_expression,
- rhs_expression,
- StringStreamToString(&lhs_ss),
- StringStreamToString(&rhs_ss),
- false);
-}
-
-// Helper function for implementing ASSERT_NEAR.
-//
-// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
-GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
- const char* expr2,
- const char* abs_error_expr,
- double val1,
- double val2,
- double abs_error);
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-// A class that enables one to stream messages to assertion macros
-class GTEST_API_ AssertHelper {
- public:
- // Constructor.
- AssertHelper(TestPartResult::Type type,
- const char* file,
- int line,
- const char* message);
- ~AssertHelper();
-
- // Message assignment is a semantic trick to enable assertion
- // streaming; see the GTEST_MESSAGE_ macro below.
- void operator=(const Message& message) const;
-
- private:
- // We put our data in a struct so that the size of the AssertHelper class can
- // be as small as possible. This is important because gcc is incapable of
- // re-using stack space even for temporary variables, so every EXPECT_EQ
- // reserves stack space for another AssertHelper.
- struct AssertHelperData {
- AssertHelperData(TestPartResult::Type t,
- const char* srcfile,
- int line_num,
- const char* msg)
- : type(t), file(srcfile), line(line_num), message(msg) { }
-
- TestPartResult::Type const type;
- const char* const file;
- int const line;
- std::string const message;
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
- };
-
- AssertHelperData* const data_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
-};
-
-enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW };
-
-GTEST_API_ GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color,
- const char* fmt,
- ...);
-
-} // namespace internal
-
-// The pure interface class that all value-parameterized tests inherit from.
-// A value-parameterized class must inherit from both ::testing::Test and
-// ::testing::WithParamInterface. In most cases that just means inheriting
-// from ::testing::TestWithParam, but more complicated test hierarchies
-// may need to inherit from Test and WithParamInterface at different levels.
-//
-// This interface has support for accessing the test parameter value via
-// the GetParam() method.
-//
-// Use it with one of the parameter generator defining functions, like Range(),
-// Values(), ValuesIn(), Bool(), and Combine().
-//
-// class FooTest : public ::testing::TestWithParam<int> {
-// protected:
-// FooTest() {
-// // Can use GetParam() here.
-// }
-// ~FooTest() override {
-// // Can use GetParam() here.
-// }
-// void SetUp() override {
-// // Can use GetParam() here.
-// }
-// void TearDown override {
-// // Can use GetParam() here.
-// }
-// };
-// TEST_P(FooTest, DoesBar) {
-// // Can use GetParam() method here.
-// Foo foo;
-// ASSERT_TRUE(foo.DoesBar(GetParam()));
-// }
-// INSTANTIATE_TEST_SUITE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
-
-template <typename T>
-class WithParamInterface {
- public:
- typedef T ParamType;
- virtual ~WithParamInterface() {}
-
- // The current parameter value. Is also available in the test fixture's
- // constructor.
- static const ParamType& GetParam() {
- GTEST_CHECK_(parameter_ != nullptr)
- << "GetParam() can only be called inside a value-parameterized test "
- << "-- did you intend to write TEST_P instead of TEST_F?";
- return *parameter_;
- }
-
- private:
- // Sets parameter value. The caller is responsible for making sure the value
- // remains alive and unchanged throughout the current test.
- static void SetParam(const ParamType* parameter) {
- parameter_ = parameter;
- }
-
- // Static value used for accessing parameter during a test lifetime.
- static const ParamType* parameter_;
-
- // TestClass must be a subclass of WithParamInterface<T> and Test.
- template <class TestClass> friend class internal::ParameterizedTestFactory;
-};
-
-template <typename T>
-const T* WithParamInterface<T>::parameter_ = nullptr;
-
-// Most value-parameterized classes can ignore the existence of
-// WithParamInterface, and can just inherit from ::testing::TestWithParam.
-
-template <typename T>
-class TestWithParam : public Test, public WithParamInterface<T> {
-};
-
-// Macros for indicating success/failure in test code.
-
-// Skips test in runtime.
-// Skipping test aborts current function.
-// Skipped tests are neither successful nor failed.
-#define GTEST_SKIP() GTEST_SKIP_("Skipped")
-
-// ADD_FAILURE unconditionally adds a failure to the current test.
-// SUCCEED generates a success - it doesn't automatically make the
-// current test successful, as a test is only successful when it has
-// no failure.
-//
-// EXPECT_* verifies that a certain condition is satisfied. If not,
-// it behaves like ADD_FAILURE. In particular:
-//
-// EXPECT_TRUE verifies that a Boolean condition is true.
-// EXPECT_FALSE verifies that a Boolean condition is false.
-//
-// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
-// that they will also abort the current function on failure. People
-// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
-// writing data-driven tests often find themselves using ADD_FAILURE
-// and EXPECT_* more.
-
-// Generates a nonfatal failure with a generic message.
-#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
-
-// Generates a nonfatal failure at the given source file location with
-// a generic message.
-#define ADD_FAILURE_AT(file, line) \
- GTEST_MESSAGE_AT_(file, line, "Failed", \
- ::testing::TestPartResult::kNonFatalFailure)
-
-// Generates a fatal failure with a generic message.
-#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
-
-// Like GTEST_FAIL(), but at the given source file location.
-#define GTEST_FAIL_AT(file, line) \
- GTEST_MESSAGE_AT_(file, line, "Failed", \
- ::testing::TestPartResult::kFatalFailure)
-
-// Define this macro to 1 to omit the definition of FAIL(), which is a
-// generic name and clashes with some other libraries.
-#if !GTEST_DONT_DEFINE_FAIL
-# define FAIL() GTEST_FAIL()
-#endif
-
-// Generates a success with a generic message.
-#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
-
-// Define this macro to 1 to omit the definition of SUCCEED(), which
-// is a generic name and clashes with some other libraries.
-#if !GTEST_DONT_DEFINE_SUCCEED
-# define SUCCEED() GTEST_SUCCEED()
-#endif
-
-// Macros for testing exceptions.
-//
-// * {ASSERT|EXPECT}_THROW(statement, expected_exception):
-// Tests that the statement throws the expected exception.
-// * {ASSERT|EXPECT}_NO_THROW(statement):
-// Tests that the statement doesn't throw any exception.
-// * {ASSERT|EXPECT}_ANY_THROW(statement):
-// Tests that the statement throws an exception.
-
-#define EXPECT_THROW(statement, expected_exception) \
- GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_NO_THROW(statement) \
- GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_ANY_THROW(statement) \
- GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_THROW(statement, expected_exception) \
- GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
-#define ASSERT_NO_THROW(statement) \
- GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
-#define ASSERT_ANY_THROW(statement) \
- GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
-
-// Boolean assertions. Condition can be either a Boolean expression or an
-// AssertionResult. For more information on how to use AssertionResult with
-// these macros see comments on that class.
-#define EXPECT_TRUE(condition) \
- GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
- GTEST_NONFATAL_FAILURE_)
-#define EXPECT_FALSE(condition) \
- GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
- GTEST_NONFATAL_FAILURE_)
-#define ASSERT_TRUE(condition) \
- GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
- GTEST_FATAL_FAILURE_)
-#define ASSERT_FALSE(condition) \
- GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
- GTEST_FATAL_FAILURE_)
-
-// Macros for testing equalities and inequalities.
-//
-// * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2
-// * {ASSERT|EXPECT}_NE(v1, v2): Tests that v1 != v2
-// * {ASSERT|EXPECT}_LT(v1, v2): Tests that v1 < v2
-// * {ASSERT|EXPECT}_LE(v1, v2): Tests that v1 <= v2
-// * {ASSERT|EXPECT}_GT(v1, v2): Tests that v1 > v2
-// * {ASSERT|EXPECT}_GE(v1, v2): Tests that v1 >= v2
-//
-// When they are not, Google Test prints both the tested expressions and
-// their actual values. The values must be compatible built-in types,
-// or you will get a compiler error. By "compatible" we mean that the
-// values can be compared by the respective operator.
-//
-// Note:
-//
-// 1. It is possible to make a user-defined type work with
-// {ASSERT|EXPECT}_??(), but that requires overloading the
-// comparison operators and is thus discouraged by the Google C++
-// Usage Guide. Therefore, you are advised to use the
-// {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
-// equal.
-//
-// 2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
-// pointers (in particular, C strings). Therefore, if you use it
-// with two C strings, you are testing how their locations in memory
-// are related, not how their content is related. To compare two C
-// strings by content, use {ASSERT|EXPECT}_STR*().
-//
-// 3. {ASSERT|EXPECT}_EQ(v1, v2) is preferred to
-// {ASSERT|EXPECT}_TRUE(v1 == v2), as the former tells you
-// what the actual value is when it fails, and similarly for the
-// other comparisons.
-//
-// 4. Do not depend on the order in which {ASSERT|EXPECT}_??()
-// evaluate their arguments, which is undefined.
-//
-// 5. These macros evaluate their arguments exactly once.
-//
-// Examples:
-//
-// EXPECT_NE(Foo(), 5);
-// EXPECT_EQ(a_pointer, NULL);
-// ASSERT_LT(i, array_size);
-// ASSERT_GT(records.size(), 0) << "There is no record left.";
-
-#define EXPECT_EQ(val1, val2) \
- EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
-#define EXPECT_NE(val1, val2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
-#define EXPECT_LE(val1, val2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
-#define EXPECT_LT(val1, val2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
-#define EXPECT_GE(val1, val2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
-#define EXPECT_GT(val1, val2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
-
-#define GTEST_ASSERT_EQ(val1, val2) \
- ASSERT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
-#define GTEST_ASSERT_NE(val1, val2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
-#define GTEST_ASSERT_LE(val1, val2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
-#define GTEST_ASSERT_LT(val1, val2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
-#define GTEST_ASSERT_GE(val1, val2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
-#define GTEST_ASSERT_GT(val1, val2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
-
-// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
-// ASSERT_XY(), which clashes with some users' own code.
-
-#if !GTEST_DONT_DEFINE_ASSERT_EQ
-# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
-#endif
-
-#if !GTEST_DONT_DEFINE_ASSERT_NE
-# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
-#endif
-
-#if !GTEST_DONT_DEFINE_ASSERT_LE
-# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
-#endif
-
-#if !GTEST_DONT_DEFINE_ASSERT_LT
-# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
-#endif
-
-#if !GTEST_DONT_DEFINE_ASSERT_GE
-# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
-#endif
-
-#if !GTEST_DONT_DEFINE_ASSERT_GT
-# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
-#endif
-
-// C-string Comparisons. All tests treat NULL and any non-NULL string
-// as different. Two NULLs are equal.
-//
-// * {ASSERT|EXPECT}_STREQ(s1, s2): Tests that s1 == s2
-// * {ASSERT|EXPECT}_STRNE(s1, s2): Tests that s1 != s2
-// * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
-// * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
-//
-// For wide or narrow string objects, you can use the
-// {ASSERT|EXPECT}_??() macros.
-//
-// Don't depend on the order in which the arguments are evaluated,
-// which is undefined.
-//
-// These macros evaluate their arguments exactly once.
-
-#define EXPECT_STREQ(s1, s2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2)
-#define EXPECT_STRNE(s1, s2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
-#define EXPECT_STRCASEEQ(s1, s2) \
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
-#define EXPECT_STRCASENE(s1, s2)\
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
-
-#define ASSERT_STREQ(s1, s2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, s1, s2)
-#define ASSERT_STRNE(s1, s2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
-#define ASSERT_STRCASEEQ(s1, s2) \
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, s1, s2)
-#define ASSERT_STRCASENE(s1, s2)\
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
-
-// Macros for comparing floating-point numbers.
-//
-// * {ASSERT|EXPECT}_FLOAT_EQ(val1, val2):
-// Tests that two float values are almost equal.
-// * {ASSERT|EXPECT}_DOUBLE_EQ(val1, val2):
-// Tests that two double values are almost equal.
-// * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
-// Tests that v1 and v2 are within the given distance to each other.
-//
-// Google Test uses ULP-based comparison to automatically pick a default
-// error bound that is appropriate for the operands. See the
-// FloatingPoint template class in gtest-internal.h if you are
-// interested in the implementation details.
-
-#define EXPECT_FLOAT_EQ(val1, val2)\
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
- val1, val2)
-
-#define EXPECT_DOUBLE_EQ(val1, val2)\
- EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
- val1, val2)
-
-#define ASSERT_FLOAT_EQ(val1, val2)\
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
- val1, val2)
-
-#define ASSERT_DOUBLE_EQ(val1, val2)\
- ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
- val1, val2)
-
-#define EXPECT_NEAR(val1, val2, abs_error)\
- EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
- val1, val2, abs_error)
-
-#define ASSERT_NEAR(val1, val2, abs_error)\
- ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
- val1, val2, abs_error)
-
-// These predicate format functions work on floating-point values, and
-// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
-//
-// EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
-
-// Asserts that val1 is less than, or almost equal to, val2. Fails
-// otherwise. In particular, it fails if either val1 or val2 is NaN.
-GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
- float val1, float val2);
-GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
- double val1, double val2);
-
-
-#if GTEST_OS_WINDOWS
-
-// Macros that test for HRESULT failure and success, these are only useful
-// on Windows, and rely on Windows SDK macros and APIs to compile.
-//
-// * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
-//
-// When expr unexpectedly fails or succeeds, Google Test prints the
-// expected result and the actual result with both a human-readable
-// string representation of the error, if available, as well as the
-// hex result code.
-# define EXPECT_HRESULT_SUCCEEDED(expr) \
- EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-
-# define ASSERT_HRESULT_SUCCEEDED(expr) \
- ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-
-# define EXPECT_HRESULT_FAILED(expr) \
- EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
-
-# define ASSERT_HRESULT_FAILED(expr) \
- ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
-
-#endif // GTEST_OS_WINDOWS
-
-// Macros that execute statement and check that it doesn't generate new fatal
-// failures in the current thread.
-//
-// * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
-//
-// Examples:
-//
-// EXPECT_NO_FATAL_FAILURE(Process());
-// ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
-//
-#define ASSERT_NO_FATAL_FAILURE(statement) \
- GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
-#define EXPECT_NO_FATAL_FAILURE(statement) \
- GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
-
-// Causes a trace (including the given source file path and line number,
-// and the given message) to be included in every test failure message generated
-// by code in the scope of the lifetime of an instance of this class. The effect
-// is undone with the destruction of the instance.
-//
-// The message argument can be anything streamable to std::ostream.
-//
-// Example:
-// testing::ScopedTrace trace("file.cc", 123, "message");
-//
-class GTEST_API_ ScopedTrace {
- public:
- // The c'tor pushes the given source file location and message onto
- // a trace stack maintained by Google Test.
-
- // Template version. Uses Message() to convert the values into strings.
- // Slow, but flexible.
- template <typename T>
- ScopedTrace(const char* file, int line, const T& message) {
- PushTrace(file, line, (Message() << message).GetString());
- }
-
- // Optimize for some known types.
- ScopedTrace(const char* file, int line, const char* message) {
- PushTrace(file, line, message ? message : "(null)");
- }
-
- ScopedTrace(const char* file, int line, const std::string& message) {
- PushTrace(file, line, message);
- }
-
- // The d'tor pops the info pushed by the c'tor.
- //
- // Note that the d'tor is not virtual in order to be efficient.
- // Don't inherit from ScopedTrace!
- ~ScopedTrace();
-
- private:
- void PushTrace(const char* file, int line, std::string message);
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
-} GTEST_ATTRIBUTE_UNUSED_; // A ScopedTrace object does its job in its
- // c'tor and d'tor. Therefore it doesn't
- // need to be used otherwise.
-
-// Causes a trace (including the source file path, the current line
-// number, and the given message) to be included in every test failure
-// message generated by code in the current scope. The effect is
-// undone when the control leaves the current scope.
-//
-// The message argument can be anything streamable to std::ostream.
-//
-// In the implementation, we include the current line number as part
-// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
-// to appear in the same block - as long as they are on different
-// lines.
-//
-// Assuming that each thread maintains its own stack of traces.
-// Therefore, a SCOPED_TRACE() would (correctly) only affect the
-// assertions in its own thread.
-#define SCOPED_TRACE(message) \
- ::testing::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
- __FILE__, __LINE__, (message))
-
-// Compile-time assertion for type equality.
-// StaticAssertTypeEq<type1, type2>() compiles if and only if type1 and type2
-// are the same type. The value it returns is not interesting.
-//
-// Instead of making StaticAssertTypeEq a class template, we make it a
-// function template that invokes a helper class template. This
-// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
-// defining objects of that type.
-//
-// CAVEAT:
-//
-// When used inside a method of a class template,
-// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
-// instantiated. For example, given:
-//
-// template <typename T> class Foo {
-// public:
-// void Bar() { testing::StaticAssertTypeEq<int, T>(); }
-// };
-//
-// the code:
-//
-// void Test1() { Foo<bool> foo; }
-//
-// will NOT generate a compiler error, as Foo<bool>::Bar() is never
-// actually instantiated. Instead, you need:
-//
-// void Test2() { Foo<bool> foo; foo.Bar(); }
-//
-// to cause a compiler error.
-template <typename T1, typename T2>
-constexpr bool StaticAssertTypeEq() noexcept {
- static_assert(std::is_same<T1, T2>::value,
- "type1 and type2 are not the same type");
- return true;
-}
-
-// Defines a test.
-//
-// The first parameter is the name of the test suite, and the second
-// parameter is the name of the test within the test suite.
-//
-// The convention is to end the test suite name with "Test". For
-// example, a test suite for the Foo class can be named FooTest.
-//
-// Test code should appear between braces after an invocation of
-// this macro. Example:
-//
-// TEST(FooTest, InitializesCorrectly) {
-// Foo foo;
-// EXPECT_TRUE(foo.StatusIsOK());
-// }
-
-// Note that we call GetTestTypeId() instead of GetTypeId<
-// ::testing::Test>() here to get the type ID of testing::Test. This
-// is to work around a suspected linker bug when using Google Test as
-// a framework on Mac OS X. The bug causes GetTypeId<
-// ::testing::Test>() to return different values depending on whether
-// the call is from the Google Test framework itself or from user test
-// code. GetTestTypeId() is guaranteed to always return the same
-// value, as it always calls GetTypeId<>() from the Google Test
-// framework.
-#define GTEST_TEST(test_suite_name, test_name) \
- GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \
- ::testing::internal::GetTestTypeId())
-
-// Define this macro to 1 to omit the definition of TEST(), which
-// is a generic name and clashes with some other libraries.
-#if !GTEST_DONT_DEFINE_TEST
-#define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)
-#endif
-
-// Defines a test that uses a test fixture.
-//
-// The first parameter is the name of the test fixture class, which
-// also doubles as the test suite name. The second parameter is the
-// name of the test within the test suite.
-//
-// A test fixture class must be declared earlier. The user should put
-// the test code between braces after using this macro. Example:
-//
-// class FooTest : public testing::Test {
-// protected:
-// void SetUp() override { b_.AddElement(3); }
-//
-// Foo a_;
-// Foo b_;
-// };
-//
-// TEST_F(FooTest, InitializesCorrectly) {
-// EXPECT_TRUE(a_.StatusIsOK());
-// }
-//
-// TEST_F(FooTest, ReturnsElementCountCorrectly) {
-// EXPECT_EQ(a_.size(), 0);
-// EXPECT_EQ(b_.size(), 1);
-// }
-//
-// GOOGLETEST_CM0011 DO NOT DELETE
-#define TEST_F(test_fixture, test_name)\
- GTEST_TEST_(test_fixture, test_name, test_fixture, \
- ::testing::internal::GetTypeId<test_fixture>())
-
-// Returns a path to temporary directory.
-// Tries to determine an appropriate directory for the platform.
-GTEST_API_ std::string TempDir();
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-// Dynamically registers a test with the framework.
-//
-// This is an advanced API only to be used when the `TEST` macros are
-// insufficient. The macros should be preferred when possible, as they avoid
-// most of the complexity of calling this function.
-//
-// The `factory` argument is a factory callable (move-constructible) object or
-// function pointer that creates a new instance of the Test object. It
-// handles ownership to the caller. The signature of the callable is
-// `Fixture*()`, where `Fixture` is the test fixture class for the test. All
-// tests registered with the same `test_suite_name` must return the same
-// fixture type. This is checked at runtime.
-//
-// The framework will infer the fixture class from the factory and will call
-// the `SetUpTestSuite` and `TearDownTestSuite` for it.
-//
-// Must be called before `RUN_ALL_TESTS()` is invoked, otherwise behavior is
-// undefined.
-//
-// Use case example:
-//
-// class MyFixture : public ::testing::Test {
-// public:
-// // All of these optional, just like in regular macro usage.
-// static void SetUpTestSuite() { ... }
-// static void TearDownTestSuite() { ... }
-// void SetUp() override { ... }
-// void TearDown() override { ... }
-// };
-//
-// class MyTest : public MyFixture {
-// public:
-// explicit MyTest(int data) : data_(data) {}
-// void TestBody() override { ... }
-//
-// private:
-// int data_;
-// };
-//
-// void RegisterMyTests(const std::vector<int>& values) {
-// for (int v : values) {
-// ::testing::RegisterTest(
-// "MyFixture", ("Test" + std::to_string(v)).c_str(), nullptr,
-// std::to_string(v).c_str(),
-// __FILE__, __LINE__,
-// // Important to use the fixture type as the return type here.
-// [=]() -> MyFixture* { return new MyTest(v); });
-// }
-// }
-// ...
-// int main(int argc, char** argv) {
-// std::vector<int> values_to_test = LoadValuesFromConfig();
-// RegisterMyTests(values_to_test);
-// ...
-// return RUN_ALL_TESTS();
-// }
-//
-template <int&... ExplicitParameterBarrier, typename Factory>
-TestInfo* RegisterTest(const char* test_suite_name, const char* test_name,
- const char* type_param, const char* value_param,
- const char* file, int line, Factory factory) {
- using TestT = typename std::remove_pointer<decltype(factory())>::type;
-
- class FactoryImpl : public internal::TestFactoryBase {
- public:
- explicit FactoryImpl(Factory f) : factory_(std::move(f)) {}
- Test* CreateTest() override { return factory_(); }
-
- private:
- Factory factory_;
- };
-
- return internal::MakeAndRegisterTestInfo(
- test_suite_name, test_name, type_param, value_param,
- internal::CodeLocation(file, line), internal::GetTypeId<TestT>(),
- internal::SuiteApiResolver<TestT>::GetSetUpCaseOrSuite(file, line),
- internal::SuiteApiResolver<TestT>::GetTearDownCaseOrSuite(file, line),
- new FactoryImpl{std::move(factory)});
-}
-
-} // namespace testing
-
-// Use this function in main() to run all tests. It returns 0 if all
-// tests are successful, or 1 otherwise.
-//
-// RUN_ALL_TESTS() should be invoked after the command line has been
-// parsed by InitGoogleTest().
-//
-// This function was formerly a macro; thus, it is in the global
-// namespace and has an all-caps name.
-int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
-
-inline int RUN_ALL_TESTS() {
- return ::testing::UnitTest::GetInstance()->Run();
-}
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_H_
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command
-// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
-//
-// Implements a family of generic predicate assertion macros.
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
-#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
-
-#include "gtest/gtest.h"
-
-namespace testing {
-
-// This header implements a family of generic predicate assertion
-// macros:
-//
-// ASSERT_PRED_FORMAT1(pred_format, v1)
-// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
-// ...
-//
-// where pred_format is a function or functor that takes n (in the
-// case of ASSERT_PRED_FORMATn) values and their source expression
-// text, and returns a testing::AssertionResult. See the definition
-// of ASSERT_EQ in gtest.h for an example.
-//
-// If you don't care about formatting, you can use the more
-// restrictive version:
-//
-// ASSERT_PRED1(pred, v1)
-// ASSERT_PRED2(pred, v1, v2)
-// ...
-//
-// where pred is an n-ary function or functor that returns bool,
-// and the values v1, v2, ..., must support the << operator for
-// streaming to std::ostream.
-//
-// We also define the EXPECT_* variations.
-//
-// For now we only support predicates whose arity is at most 5.
-// Please email googletestframework@googlegroups.com if you need
-// support for higher arities.
-
-// GTEST_ASSERT_ is the basic statement to which all of the assertions
-// in this file reduce. Don't use this in your code.
-
-#define GTEST_ASSERT_(expression, on_failure) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const ::testing::AssertionResult gtest_ar = (expression)) \
- ; \
- else \
- on_failure(gtest_ar.failure_message())
-
-
-// Helper function for implementing {EXPECT|ASSERT}_PRED1. Don't use
-// this in your code.
-template <typename Pred,
- typename T1>
-AssertionResult AssertPred1Helper(const char* pred_text,
- const char* e1,
- Pred pred,
- const T1& v1) {
- if (pred(v1)) return AssertionSuccess();
-
- return AssertionFailure()
- << pred_text << "(" << e1 << ") evaluates to false, where"
- << "\n"
- << e1 << " evaluates to " << ::testing::PrintToString(v1);
-}
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
-// Don't use this in your code.
-#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
- GTEST_ASSERT_(pred_format(#v1, v1), \
- on_failure)
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED1. Don't use
-// this in your code.
-#define GTEST_PRED1_(pred, v1, on_failure)\
- GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
- #v1, \
- pred, \
- v1), on_failure)
-
-// Unary predicate assertion macros.
-#define EXPECT_PRED_FORMAT1(pred_format, v1) \
- GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_PRED1(pred, v1) \
- GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_PRED_FORMAT1(pred_format, v1) \
- GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
-#define ASSERT_PRED1(pred, v1) \
- GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
-
-
-
-// Helper function for implementing {EXPECT|ASSERT}_PRED2. Don't use
-// this in your code.
-template <typename Pred,
- typename T1,
- typename T2>
-AssertionResult AssertPred2Helper(const char* pred_text,
- const char* e1,
- const char* e2,
- Pred pred,
- const T1& v1,
- const T2& v2) {
- if (pred(v1, v2)) return AssertionSuccess();
-
- return AssertionFailure()
- << pred_text << "(" << e1 << ", " << e2
- << ") evaluates to false, where"
- << "\n"
- << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
- << e2 << " evaluates to " << ::testing::PrintToString(v2);
-}
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
-// Don't use this in your code.
-#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
- GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
- on_failure)
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED2. Don't use
-// this in your code.
-#define GTEST_PRED2_(pred, v1, v2, on_failure)\
- GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
- #v1, \
- #v2, \
- pred, \
- v1, \
- v2), on_failure)
-
-// Binary predicate assertion macros.
-#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
- GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_PRED2(pred, v1, v2) \
- GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
- GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
-#define ASSERT_PRED2(pred, v1, v2) \
- GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
-
-
-
-// Helper function for implementing {EXPECT|ASSERT}_PRED3. Don't use
-// this in your code.
-template <typename Pred,
- typename T1,
- typename T2,
- typename T3>
-AssertionResult AssertPred3Helper(const char* pred_text,
- const char* e1,
- const char* e2,
- const char* e3,
- Pred pred,
- const T1& v1,
- const T2& v2,
- const T3& v3) {
- if (pred(v1, v2, v3)) return AssertionSuccess();
-
- return AssertionFailure()
- << pred_text << "(" << e1 << ", " << e2 << ", " << e3
- << ") evaluates to false, where"
- << "\n"
- << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
- << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
- << e3 << " evaluates to " << ::testing::PrintToString(v3);
-}
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
-// Don't use this in your code.
-#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
- GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
- on_failure)
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED3. Don't use
-// this in your code.
-#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
- GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
- #v1, \
- #v2, \
- #v3, \
- pred, \
- v1, \
- v2, \
- v3), on_failure)
-
-// Ternary predicate assertion macros.
-#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
- GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_PRED3(pred, v1, v2, v3) \
- GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
- GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
-#define ASSERT_PRED3(pred, v1, v2, v3) \
- GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
-
-
-
-// Helper function for implementing {EXPECT|ASSERT}_PRED4. Don't use
-// this in your code.
-template <typename Pred,
- typename T1,
- typename T2,
- typename T3,
- typename T4>
-AssertionResult AssertPred4Helper(const char* pred_text,
- const char* e1,
- const char* e2,
- const char* e3,
- const char* e4,
- Pred pred,
- const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4) {
- if (pred(v1, v2, v3, v4)) return AssertionSuccess();
-
- return AssertionFailure()
- << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
- << ") evaluates to false, where"
- << "\n"
- << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
- << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
- << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
- << e4 << " evaluates to " << ::testing::PrintToString(v4);
-}
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
-// Don't use this in your code.
-#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
- GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
- on_failure)
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED4. Don't use
-// this in your code.
-#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
- GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
- #v1, \
- #v2, \
- #v3, \
- #v4, \
- pred, \
- v1, \
- v2, \
- v3, \
- v4), on_failure)
-
-// 4-ary predicate assertion macros.
-#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
- GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
- GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
- GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
-#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
- GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
-
-
-
-// Helper function for implementing {EXPECT|ASSERT}_PRED5. Don't use
-// this in your code.
-template <typename Pred,
- typename T1,
- typename T2,
- typename T3,
- typename T4,
- typename T5>
-AssertionResult AssertPred5Helper(const char* pred_text,
- const char* e1,
- const char* e2,
- const char* e3,
- const char* e4,
- const char* e5,
- Pred pred,
- const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4,
- const T5& v5) {
- if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
-
- return AssertionFailure()
- << pred_text << "(" << e1 << ", " << e2 << ", " << e3 << ", " << e4
- << ", " << e5 << ") evaluates to false, where"
- << "\n"
- << e1 << " evaluates to " << ::testing::PrintToString(v1) << "\n"
- << e2 << " evaluates to " << ::testing::PrintToString(v2) << "\n"
- << e3 << " evaluates to " << ::testing::PrintToString(v3) << "\n"
- << e4 << " evaluates to " << ::testing::PrintToString(v4) << "\n"
- << e5 << " evaluates to " << ::testing::PrintToString(v5);
-}
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
-// Don't use this in your code.
-#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
- GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
- on_failure)
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED5. Don't use
-// this in your code.
-#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
- GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
- #v1, \
- #v2, \
- #v3, \
- #v4, \
- #v5, \
- pred, \
- v1, \
- v2, \
- v3, \
- v4, \
- v5), on_failure)
-
-// 5-ary predicate assertion macros.
-#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
- GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
- GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
- GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
-#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
- GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
-
-
-
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Google C++ Testing and Mocking Framework definitions useful in production code.
-// GOOGLETEST_CM0003 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
-#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
-
-// When you need to test the private or protected members of a class,
-// use the FRIEND_TEST macro to declare your tests as friends of the
-// class. For example:
-//
-// class MyClass {
-// private:
-// void PrivateMethod();
-// FRIEND_TEST(MyClassTest, PrivateMethodWorks);
-// };
-//
-// class MyClassTest : public testing::Test {
-// // ...
-// };
-//
-// TEST_F(MyClassTest, PrivateMethodWorks) {
-// // Can call MyClass::PrivateMethod() here.
-// }
-//
-// Note: The test class must be in the same namespace as the class being tested.
-// For example, putting MyClassTest in an anonymous namespace will not work.
-
-#define FRIEND_TEST(test_case_name, test_name)\
-friend class test_case_name##_##test_name##_Test
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+++ /dev/null
-# Customization Points
-
-The custom directory is an injection point for custom user configurations.
-
-## Header `gtest.h`
-
-### The following macros can be defined:
-
-* `GTEST_OS_STACK_TRACE_GETTER_` - The name of an implementation of
- `OsStackTraceGetterInterface`.
-* `GTEST_CUSTOM_TEMPDIR_FUNCTION_` - An override for `testing::TempDir()`. See
- `testing::TempDir` for semantics and signature.
-
-## Header `gtest-port.h`
-
-The following macros can be defined:
-
-### Flag related macros:
-
-* `GTEST_FLAG(flag_name)`
-* `GTEST_USE_OWN_FLAGFILE_FLAG_` - Define to 0 when the system provides its
- own flagfile flag parsing.
-* `GTEST_DECLARE_bool_(name)`
-* `GTEST_DECLARE_int32_(name)`
-* `GTEST_DECLARE_string_(name)`
-* `GTEST_DEFINE_bool_(name, default_val, doc)`
-* `GTEST_DEFINE_int32_(name, default_val, doc)`
-* `GTEST_DEFINE_string_(name, default_val, doc)`
-
-### Logging:
-
-* `GTEST_LOG_(severity)`
-* `GTEST_CHECK_(condition)`
-* Functions `LogToStderr()` and `FlushInfoLog()` have to be provided too.
-
-### Threading:
-
-* `GTEST_HAS_NOTIFICATION_` - Enabled if Notification is already provided.
-* `GTEST_HAS_MUTEX_AND_THREAD_LOCAL_` - Enabled if `Mutex` and `ThreadLocal`
- are already provided. Must also provide `GTEST_DECLARE_STATIC_MUTEX_(mutex)`
- and `GTEST_DEFINE_STATIC_MUTEX_(mutex)`
-* `GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)`
-* `GTEST_LOCK_EXCLUDED_(locks)`
-
-### Underlying library support features
-
-* `GTEST_HAS_CXXABI_H_`
-
-### Exporting API symbols:
-
-* `GTEST_API_` - Specifier for exported symbols.
-
-## Header `gtest-printers.h`
-
-* See documentation at `gtest/gtest-printers.h` for details on how to define a
- custom printer.
+++ /dev/null
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Injection point for custom user configurations. See README for details
-//
-// ** Custom implementation starts here **
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
+++ /dev/null
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// This file provides an injection point for custom printers in a local
-// installation of gTest.
-// It will be included from gtest-printers.h and the overrides in this file
-// will be visible to everyone.
-//
-// Injection point for custom user configurations. See README for details
-//
-// ** Custom implementation starts here **
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
+++ /dev/null
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Injection point for custom user configurations. See README for details
-//
-// ** Custom implementation starts here **
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file defines internal utilities needed for implementing
-// death tests. They are subject to change without notice.
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
-
-#include "gtest/gtest-matchers.h"
-#include "gtest/internal/gtest-internal.h"
-
-#include <stdio.h>
-#include <memory>
-
-namespace testing {
-namespace internal {
-
-GTEST_DECLARE_string_(internal_run_death_test);
-
-// Names of the flags (needed for parsing Google Test flags).
-const char kDeathTestStyleFlag[] = "death_test_style";
-const char kDeathTestUseFork[] = "death_test_use_fork";
-const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
-
-#if GTEST_HAS_DEATH_TEST
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-// DeathTest is a class that hides much of the complexity of the
-// GTEST_DEATH_TEST_ macro. It is abstract; its static Create method
-// returns a concrete class that depends on the prevailing death test
-// style, as defined by the --gtest_death_test_style and/or
-// --gtest_internal_run_death_test flags.
-
-// In describing the results of death tests, these terms are used with
-// the corresponding definitions:
-//
-// exit status: The integer exit information in the format specified
-// by wait(2)
-// exit code: The integer code passed to exit(3), _exit(2), or
-// returned from main()
-class GTEST_API_ DeathTest {
- public:
- // Create returns false if there was an error determining the
- // appropriate action to take for the current death test; for example,
- // if the gtest_death_test_style flag is set to an invalid value.
- // The LastMessage method will return a more detailed message in that
- // case. Otherwise, the DeathTest pointer pointed to by the "test"
- // argument is set. If the death test should be skipped, the pointer
- // is set to NULL; otherwise, it is set to the address of a new concrete
- // DeathTest object that controls the execution of the current test.
- static bool Create(const char* statement, Matcher<const std::string&> matcher,
- const char* file, int line, DeathTest** test);
- DeathTest();
- virtual ~DeathTest() { }
-
- // A helper class that aborts a death test when it's deleted.
- class ReturnSentinel {
- public:
- explicit ReturnSentinel(DeathTest* test) : test_(test) { }
- ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
- private:
- DeathTest* const test_;
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
- } GTEST_ATTRIBUTE_UNUSED_;
-
- // An enumeration of possible roles that may be taken when a death
- // test is encountered. EXECUTE means that the death test logic should
- // be executed immediately. OVERSEE means that the program should prepare
- // the appropriate environment for a child process to execute the death
- // test, then wait for it to complete.
- enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
-
- // An enumeration of the three reasons that a test might be aborted.
- enum AbortReason {
- TEST_ENCOUNTERED_RETURN_STATEMENT,
- TEST_THREW_EXCEPTION,
- TEST_DID_NOT_DIE
- };
-
- // Assumes one of the above roles.
- virtual TestRole AssumeRole() = 0;
-
- // Waits for the death test to finish and returns its status.
- virtual int Wait() = 0;
-
- // Returns true if the death test passed; that is, the test process
- // exited during the test, its exit status matches a user-supplied
- // predicate, and its stderr output matches a user-supplied regular
- // expression.
- // The user-supplied predicate may be a macro expression rather
- // than a function pointer or functor, or else Wait and Passed could
- // be combined.
- virtual bool Passed(bool exit_status_ok) = 0;
-
- // Signals that the death test did not die as expected.
- virtual void Abort(AbortReason reason) = 0;
-
- // Returns a human-readable outcome message regarding the outcome of
- // the last death test.
- static const char* LastMessage();
-
- static void set_last_death_test_message(const std::string& message);
-
- private:
- // A string containing a description of the outcome of the last death test.
- static std::string last_death_test_message_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
-};
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-// Factory interface for death tests. May be mocked out for testing.
-class DeathTestFactory {
- public:
- virtual ~DeathTestFactory() { }
- virtual bool Create(const char* statement,
- Matcher<const std::string&> matcher, const char* file,
- int line, DeathTest** test) = 0;
-};
-
-// A concrete DeathTestFactory implementation for normal use.
-class DefaultDeathTestFactory : public DeathTestFactory {
- public:
- bool Create(const char* statement, Matcher<const std::string&> matcher,
- const char* file, int line, DeathTest** test) override;
-};
-
-// Returns true if exit_status describes a process that was terminated
-// by a signal, or exited normally with a nonzero exit code.
-GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
-
-// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
-// and interpreted as a regex (rather than an Eq matcher) for legacy
-// compatibility.
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(
- ::testing::internal::RE regex) {
- return ContainsRegex(regex.pattern());
-}
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
- return ContainsRegex(regex);
-}
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(
- const ::std::string& regex) {
- return ContainsRegex(regex);
-}
-
-// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
-// used directly.
-inline Matcher<const ::std::string&> MakeDeathTestMatcher(
- Matcher<const ::std::string&> matcher) {
- return matcher;
-}
-
-// Traps C++ exceptions escaping statement and reports them as test
-// failures. Note that trapping SEH exceptions is not implemented here.
-# if GTEST_HAS_EXCEPTIONS
-# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
- try { \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- } catch (const ::std::exception& gtest_exception) { \
- fprintf(\
- stderr, \
- "\n%s: Caught std::exception-derived exception escaping the " \
- "death test statement. Exception message: %s\n", \
- ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
- gtest_exception.what()); \
- fflush(stderr); \
- death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
- } catch (...) { \
- death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
- }
-
-# else
-# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
-
-# endif
-
-// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
-// ASSERT_EXIT*, and EXPECT_EXIT*.
-#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::AlwaysTrue()) { \
- ::testing::internal::DeathTest* gtest_dt; \
- if (!::testing::internal::DeathTest::Create( \
- #statement, \
- ::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \
- __FILE__, __LINE__, >est_dt)) { \
- goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
- } \
- if (gtest_dt != nullptr) { \
- std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
- switch (gtest_dt->AssumeRole()) { \
- case ::testing::internal::DeathTest::OVERSEE_TEST: \
- if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
- goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
- } \
- break; \
- case ::testing::internal::DeathTest::EXECUTE_TEST: { \
- ::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
- gtest_dt); \
- GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
- gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
- break; \
- } \
- default: \
- break; \
- } \
- } \
- } else \
- GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \
- : fail(::testing::internal::DeathTest::LastMessage())
-// The symbol "fail" here expands to something into which a message
-// can be streamed.
-
-// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
-// NDEBUG mode. In this case we need the statements to be executed and the macro
-// must accept a streamed message even though the message is never printed.
-// The regex object is not evaluated, but it is used to prevent "unused"
-// warnings and to avoid an expression that doesn't compile in debug mode.
-#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::AlwaysTrue()) { \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- } else if (!::testing::internal::AlwaysTrue()) { \
- ::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
- } else \
- ::testing::Message()
-
-// A class representing the parsed contents of the
-// --gtest_internal_run_death_test flag, as it existed when
-// RUN_ALL_TESTS was called.
-class InternalRunDeathTestFlag {
- public:
- InternalRunDeathTestFlag(const std::string& a_file,
- int a_line,
- int an_index,
- int a_write_fd)
- : file_(a_file), line_(a_line), index_(an_index),
- write_fd_(a_write_fd) {}
-
- ~InternalRunDeathTestFlag() {
- if (write_fd_ >= 0)
- posix::Close(write_fd_);
- }
-
- const std::string& file() const { return file_; }
- int line() const { return line_; }
- int index() const { return index_; }
- int write_fd() const { return write_fd_; }
-
- private:
- std::string file_;
- int line_;
- int index_;
- int write_fd_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
-};
-
-// Returns a newly created InternalRunDeathTestFlag object with fields
-// initialized from the GTEST_FLAG(internal_run_death_test) flag if
-// the flag is specified; otherwise returns NULL.
-InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
-
-#endif // GTEST_HAS_DEATH_TEST
-
-} // namespace internal
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Google Test filepath utilities
-//
-// This header file declares classes and functions used internally by
-// Google Test. They are subject to change without notice.
-//
-// This file is #included in gtest/internal/gtest-internal.h.
-// Do not include this header file separately!
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
-
-#include "gtest/internal/gtest-string.h"
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-namespace testing {
-namespace internal {
-
-// FilePath - a class for file and directory pathname manipulation which
-// handles platform-specific conventions (like the pathname separator).
-// Used for helper functions for naming files in a directory for xml output.
-// Except for Set methods, all methods are const or static, which provides an
-// "immutable value object" -- useful for peace of mind.
-// A FilePath with a value ending in a path separator ("like/this/") represents
-// a directory, otherwise it is assumed to represent a file. In either case,
-// it may or may not represent an actual file or directory in the file system.
-// Names are NOT checked for syntax correctness -- no checking for illegal
-// characters, malformed paths, etc.
-
-class GTEST_API_ FilePath {
- public:
- FilePath() : pathname_("") { }
- FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
-
- explicit FilePath(const std::string& pathname) : pathname_(pathname) {
- Normalize();
- }
-
- FilePath& operator=(const FilePath& rhs) {
- Set(rhs);
- return *this;
- }
-
- void Set(const FilePath& rhs) {
- pathname_ = rhs.pathname_;
- }
-
- const std::string& string() const { return pathname_; }
- const char* c_str() const { return pathname_.c_str(); }
-
- // Returns the current working directory, or "" if unsuccessful.
- static FilePath GetCurrentDir();
-
- // Given directory = "dir", base_name = "test", number = 0,
- // extension = "xml", returns "dir/test.xml". If number is greater
- // than zero (e.g., 12), returns "dir/test_12.xml".
- // On Windows platform, uses \ as the separator rather than /.
- static FilePath MakeFileName(const FilePath& directory,
- const FilePath& base_name,
- int number,
- const char* extension);
-
- // Given directory = "dir", relative_path = "test.xml",
- // returns "dir/test.xml".
- // On Windows, uses \ as the separator rather than /.
- static FilePath ConcatPaths(const FilePath& directory,
- const FilePath& relative_path);
-
- // Returns a pathname for a file that does not currently exist. The pathname
- // will be directory/base_name.extension or
- // directory/base_name_<number>.extension if directory/base_name.extension
- // already exists. The number will be incremented until a pathname is found
- // that does not already exist.
- // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
- // There could be a race condition if two or more processes are calling this
- // function at the same time -- they could both pick the same filename.
- static FilePath GenerateUniqueFileName(const FilePath& directory,
- const FilePath& base_name,
- const char* extension);
-
- // Returns true if and only if the path is "".
- bool IsEmpty() const { return pathname_.empty(); }
-
- // If input name has a trailing separator character, removes it and returns
- // the name, otherwise return the name string unmodified.
- // On Windows platform, uses \ as the separator, other platforms use /.
- FilePath RemoveTrailingPathSeparator() const;
-
- // Returns a copy of the FilePath with the directory part removed.
- // Example: FilePath("path/to/file").RemoveDirectoryName() returns
- // FilePath("file"). If there is no directory part ("just_a_file"), it returns
- // the FilePath unmodified. If there is no file part ("just_a_dir/") it
- // returns an empty FilePath ("").
- // On Windows platform, '\' is the path separator, otherwise it is '/'.
- FilePath RemoveDirectoryName() const;
-
- // RemoveFileName returns the directory path with the filename removed.
- // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
- // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
- // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
- // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
- // On Windows platform, '\' is the path separator, otherwise it is '/'.
- FilePath RemoveFileName() const;
-
- // Returns a copy of the FilePath with the case-insensitive extension removed.
- // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
- // FilePath("dir/file"). If a case-insensitive extension is not
- // found, returns a copy of the original FilePath.
- FilePath RemoveExtension(const char* extension) const;
-
- // Creates directories so that path exists. Returns true if successful or if
- // the directories already exist; returns false if unable to create
- // directories for any reason. Will also return false if the FilePath does
- // not represent a directory (that is, it doesn't end with a path separator).
- bool CreateDirectoriesRecursively() const;
-
- // Create the directory so that path exists. Returns true if successful or
- // if the directory already exists; returns false if unable to create the
- // directory for any reason, including if the parent directory does not
- // exist. Not named "CreateDirectory" because that's a macro on Windows.
- bool CreateFolder() const;
-
- // Returns true if FilePath describes something in the file-system,
- // either a file, directory, or whatever, and that something exists.
- bool FileOrDirectoryExists() const;
-
- // Returns true if pathname describes a directory in the file-system
- // that exists.
- bool DirectoryExists() const;
-
- // Returns true if FilePath ends with a path separator, which indicates that
- // it is intended to represent a directory. Returns false otherwise.
- // This does NOT check that a directory (or file) actually exists.
- bool IsDirectory() const;
-
- // Returns true if pathname describes a root directory. (Windows has one
- // root directory per disk drive.)
- bool IsRootDirectory() const;
-
- // Returns true if pathname describes an absolute path.
- bool IsAbsolutePath() const;
-
- private:
- // Replaces multiple consecutive separators with a single separator.
- // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
- // redundancies that might be in a pathname involving "." or "..".
- //
- // A pathname with multiple consecutive separators may occur either through
- // user error or as a result of some scripts or APIs that generate a pathname
- // with a trailing separator. On other platforms the same API or script
- // may NOT generate a pathname with a trailing "/". Then elsewhere that
- // pathname may have another "/" and pathname components added to it,
- // without checking for the separator already being there.
- // The script language and operating system may allow paths like "foo//bar"
- // but some of the functions in FilePath will not handle that correctly. In
- // particular, RemoveTrailingPathSeparator() only removes one separator, and
- // it is called in CreateDirectoriesRecursively() assuming that it will change
- // a pathname from directory syntax (trailing separator) to filename syntax.
- //
- // On Windows this method also replaces the alternate path separator '/' with
- // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
- // "bar\\foo".
-
- void Normalize();
-
- // Returns a pointer to the last occurence of a valid path separator in
- // the FilePath. On Windows, for example, both '/' and '\' are valid path
- // separators. Returns NULL if no path separator was found.
- const char* FindLastPathSeparator() const;
-
- std::string pathname_;
-}; // class FilePath
-
-} // namespace internal
-} // namespace testing
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file declares functions and macros used internally by
-// Google Test. They are subject to change without notice.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-
-#include "gtest/internal/gtest-port.h"
-
-#if GTEST_OS_LINUX
-# include <stdlib.h>
-# include <sys/types.h>
-# include <sys/wait.h>
-# include <unistd.h>
-#endif // GTEST_OS_LINUX
-
-#if GTEST_HAS_EXCEPTIONS
-# include <stdexcept>
-#endif
-
-#include <ctype.h>
-#include <float.h>
-#include <string.h>
-#include <iomanip>
-#include <limits>
-#include <map>
-#include <set>
-#include <string>
-#include <type_traits>
-#include <vector>
-
-#include "gtest/gtest-message.h"
-#include "gtest/internal/gtest-filepath.h"
-#include "gtest/internal/gtest-string.h"
-#include "gtest/internal/gtest-type-util.h"
-
-// Due to C++ preprocessor weirdness, we need double indirection to
-// concatenate two tokens when one of them is __LINE__. Writing
-//
-// foo ## __LINE__
-//
-// will result in the token foo__LINE__, instead of foo followed by
-// the current line number. For more details, see
-// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
-#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
-#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
-
-// Stringifies its argument.
-#define GTEST_STRINGIFY_(name) #name
-
-namespace proto2 { class Message; }
-
-namespace testing {
-
-// Forward declarations.
-
-class AssertionResult; // Result of an assertion.
-class Message; // Represents a failure message.
-class Test; // Represents a test.
-class TestInfo; // Information about a test.
-class TestPartResult; // Result of a test part.
-class UnitTest; // A collection of test suites.
-
-template <typename T>
-::std::string PrintToString(const T& value);
-
-namespace internal {
-
-struct TraceInfo; // Information about a trace point.
-class TestInfoImpl; // Opaque implementation of TestInfo
-class UnitTestImpl; // Opaque implementation of UnitTest
-
-// The text used in failure messages to indicate the start of the
-// stack trace.
-GTEST_API_ extern const char kStackTraceMarker[];
-
-// An IgnoredValue object can be implicitly constructed from ANY value.
-class IgnoredValue {
- struct Sink {};
- public:
- // This constructor template allows any value to be implicitly
- // converted to IgnoredValue. The object has no data member and
- // doesn't try to remember anything about the argument. We
- // deliberately omit the 'explicit' keyword in order to allow the
- // conversion to be implicit.
- // Disable the conversion if T already has a magical conversion operator.
- // Otherwise we get ambiguity.
- template <typename T,
- typename std::enable_if<!std::is_convertible<T, Sink>::value,
- int>::type = 0>
- IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit)
-};
-
-// Appends the user-supplied message to the Google-Test-generated message.
-GTEST_API_ std::string AppendUserMessage(
- const std::string& gtest_msg, const Message& user_msg);
-
-#if GTEST_HAS_EXCEPTIONS
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4275 \
-/* an exported class was derived from a class that was not exported */)
-
-// This exception is thrown by (and only by) a failed Google Test
-// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
-// are enabled). We derive it from std::runtime_error, which is for
-// errors presumably detectable only at run time. Since
-// std::runtime_error inherits from std::exception, many testing
-// frameworks know how to extract and print the message inside it.
-class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
- public:
- explicit GoogleTestFailureException(const TestPartResult& failure);
-};
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4275
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-namespace edit_distance {
-// Returns the optimal edits to go from 'left' to 'right'.
-// All edits cost the same, with replace having lower priority than
-// add/remove.
-// Simple implementation of the Wagner-Fischer algorithm.
-// See http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm
-enum EditType { kMatch, kAdd, kRemove, kReplace };
-GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
- const std::vector<size_t>& left, const std::vector<size_t>& right);
-
-// Same as above, but the input is represented as strings.
-GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
- const std::vector<std::string>& left,
- const std::vector<std::string>& right);
-
-// Create a diff of the input strings in Unified diff format.
-GTEST_API_ std::string CreateUnifiedDiff(const std::vector<std::string>& left,
- const std::vector<std::string>& right,
- size_t context = 2);
-
-} // namespace edit_distance
-
-// Calculate the diff between 'left' and 'right' and return it in unified diff
-// format.
-// If not null, stores in 'total_line_count' the total number of lines found
-// in left + right.
-GTEST_API_ std::string DiffStrings(const std::string& left,
- const std::string& right,
- size_t* total_line_count);
-
-// Constructs and returns the message for an equality assertion
-// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
-//
-// The first four parameters are the expressions used in the assertion
-// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
-// where foo is 5 and bar is 6, we have:
-//
-// expected_expression: "foo"
-// actual_expression: "bar"
-// expected_value: "5"
-// actual_value: "6"
-//
-// The ignoring_case parameter is true if and only if the assertion is a
-// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
-// be inserted into the message.
-GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
- const char* actual_expression,
- const std::string& expected_value,
- const std::string& actual_value,
- bool ignoring_case);
-
-// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
-GTEST_API_ std::string GetBoolAssertionFailureMessage(
- const AssertionResult& assertion_result,
- const char* expression_text,
- const char* actual_predicate_value,
- const char* expected_predicate_value);
-
-// This template class represents an IEEE floating-point number
-// (either single-precision or double-precision, depending on the
-// template parameters).
-//
-// The purpose of this class is to do more sophisticated number
-// comparison. (Due to round-off error, etc, it's very unlikely that
-// two floating-points will be equal exactly. Hence a naive
-// comparison by the == operation often doesn't work.)
-//
-// Format of IEEE floating-point:
-//
-// The most-significant bit being the leftmost, an IEEE
-// floating-point looks like
-//
-// sign_bit exponent_bits fraction_bits
-//
-// Here, sign_bit is a single bit that designates the sign of the
-// number.
-//
-// For float, there are 8 exponent bits and 23 fraction bits.
-//
-// For double, there are 11 exponent bits and 52 fraction bits.
-//
-// More details can be found at
-// http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
-//
-// Template parameter:
-//
-// RawType: the raw floating-point type (either float or double)
-template <typename RawType>
-class FloatingPoint {
- public:
- // Defines the unsigned integer type that has the same size as the
- // floating point number.
- typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
-
- // Constants.
-
- // # of bits in a number.
- static const size_t kBitCount = 8*sizeof(RawType);
-
- // # of fraction bits in a number.
- static const size_t kFractionBitCount =
- std::numeric_limits<RawType>::digits - 1;
-
- // # of exponent bits in a number.
- static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
-
- // The mask for the sign bit.
- static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
-
- // The mask for the fraction bits.
- static const Bits kFractionBitMask =
- ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
-
- // The mask for the exponent bits.
- static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
-
- // How many ULP's (Units in the Last Place) we want to tolerate when
- // comparing two numbers. The larger the value, the more error we
- // allow. A 0 value means that two numbers must be exactly the same
- // to be considered equal.
- //
- // The maximum error of a single floating-point operation is 0.5
- // units in the last place. On Intel CPU's, all floating-point
- // calculations are done with 80-bit precision, while double has 64
- // bits. Therefore, 4 should be enough for ordinary use.
- //
- // See the following article for more details on ULP:
- // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
- static const size_t kMaxUlps = 4;
-
- // Constructs a FloatingPoint from a raw floating-point number.
- //
- // On an Intel CPU, passing a non-normalized NAN (Not a Number)
- // around may change its bits, although the new value is guaranteed
- // to be also a NAN. Therefore, don't expect this constructor to
- // preserve the bits in x when x is a NAN.
- explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
-
- // Static methods
-
- // Reinterprets a bit pattern as a floating-point number.
- //
- // This function is needed to test the AlmostEquals() method.
- static RawType ReinterpretBits(const Bits bits) {
- FloatingPoint fp(0);
- fp.u_.bits_ = bits;
- return fp.u_.value_;
- }
-
- // Returns the floating-point number that represent positive infinity.
- static RawType Infinity() {
- return ReinterpretBits(kExponentBitMask);
- }
-
- // Returns the maximum representable finite floating-point number.
- static RawType Max();
-
- // Non-static methods
-
- // Returns the bits that represents this number.
- const Bits &bits() const { return u_.bits_; }
-
- // Returns the exponent bits of this number.
- Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
-
- // Returns the fraction bits of this number.
- Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
-
- // Returns the sign bit of this number.
- Bits sign_bit() const { return kSignBitMask & u_.bits_; }
-
- // Returns true if and only if this is NAN (not a number).
- bool is_nan() const {
- // It's a NAN if the exponent bits are all ones and the fraction
- // bits are not entirely zeros.
- return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
- }
-
- // Returns true if and only if this number is at most kMaxUlps ULP's away
- // from rhs. In particular, this function:
- //
- // - returns false if either number is (or both are) NAN.
- // - treats really large numbers as almost equal to infinity.
- // - thinks +0.0 and -0.0 are 0 DLP's apart.
- bool AlmostEquals(const FloatingPoint& rhs) const {
- // The IEEE standard says that any comparison operation involving
- // a NAN must return false.
- if (is_nan() || rhs.is_nan()) return false;
-
- return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
- <= kMaxUlps;
- }
-
- private:
- // The data type used to store the actual floating-point number.
- union FloatingPointUnion {
- RawType value_; // The raw floating-point number.
- Bits bits_; // The bits that represent the number.
- };
-
- // Converts an integer from the sign-and-magnitude representation to
- // the biased representation. More precisely, let N be 2 to the
- // power of (kBitCount - 1), an integer x is represented by the
- // unsigned number x + N.
- //
- // For instance,
- //
- // -N + 1 (the most negative number representable using
- // sign-and-magnitude) is represented by 1;
- // 0 is represented by N; and
- // N - 1 (the biggest number representable using
- // sign-and-magnitude) is represented by 2N - 1.
- //
- // Read http://en.wikipedia.org/wiki/Signed_number_representations
- // for more details on signed number representations.
- static Bits SignAndMagnitudeToBiased(const Bits &sam) {
- if (kSignBitMask & sam) {
- // sam represents a negative number.
- return ~sam + 1;
- } else {
- // sam represents a positive number.
- return kSignBitMask | sam;
- }
- }
-
- // Given two numbers in the sign-and-magnitude representation,
- // returns the distance between them as an unsigned number.
- static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
- const Bits &sam2) {
- const Bits biased1 = SignAndMagnitudeToBiased(sam1);
- const Bits biased2 = SignAndMagnitudeToBiased(sam2);
- return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
- }
-
- FloatingPointUnion u_;
-};
-
-// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
-// macro defined by <windows.h>.
-template <>
-inline float FloatingPoint<float>::Max() { return FLT_MAX; }
-template <>
-inline double FloatingPoint<double>::Max() { return DBL_MAX; }
-
-// Typedefs the instances of the FloatingPoint template class that we
-// care to use.
-typedef FloatingPoint<float> Float;
-typedef FloatingPoint<double> Double;
-
-// In order to catch the mistake of putting tests that use different
-// test fixture classes in the same test suite, we need to assign
-// unique IDs to fixture classes and compare them. The TypeId type is
-// used to hold such IDs. The user should treat TypeId as an opaque
-// type: the only operation allowed on TypeId values is to compare
-// them for equality using the == operator.
-typedef const void* TypeId;
-
-template <typename T>
-class TypeIdHelper {
- public:
- // dummy_ must not have a const type. Otherwise an overly eager
- // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
- // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
- static bool dummy_;
-};
-
-template <typename T>
-bool TypeIdHelper<T>::dummy_ = false;
-
-// GetTypeId<T>() returns the ID of type T. Different values will be
-// returned for different types. Calling the function twice with the
-// same type argument is guaranteed to return the same ID.
-template <typename T>
-TypeId GetTypeId() {
- // The compiler is required to allocate a different
- // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
- // the template. Therefore, the address of dummy_ is guaranteed to
- // be unique.
- return &(TypeIdHelper<T>::dummy_);
-}
-
-// Returns the type ID of ::testing::Test. Always call this instead
-// of GetTypeId< ::testing::Test>() to get the type ID of
-// ::testing::Test, as the latter may give the wrong result due to a
-// suspected linker bug when compiling Google Test as a Mac OS X
-// framework.
-GTEST_API_ TypeId GetTestTypeId();
-
-// Defines the abstract factory interface that creates instances
-// of a Test object.
-class TestFactoryBase {
- public:
- virtual ~TestFactoryBase() {}
-
- // Creates a test instance to run. The instance is both created and destroyed
- // within TestInfoImpl::Run()
- virtual Test* CreateTest() = 0;
-
- protected:
- TestFactoryBase() {}
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
-};
-
-// This class provides implementation of TeastFactoryBase interface.
-// It is used in TEST and TEST_F macros.
-template <class TestClass>
-class TestFactoryImpl : public TestFactoryBase {
- public:
- Test* CreateTest() override { return new TestClass; }
-};
-
-#if GTEST_OS_WINDOWS
-
-// Predicate-formatters for implementing the HRESULT checking macros
-// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
-// We pass a long instead of HRESULT to avoid causing an
-// include dependency for the HRESULT type.
-GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
- long hr); // NOLINT
-GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
- long hr); // NOLINT
-
-#endif // GTEST_OS_WINDOWS
-
-// Types of SetUpTestSuite() and TearDownTestSuite() functions.
-using SetUpTestSuiteFunc = void (*)();
-using TearDownTestSuiteFunc = void (*)();
-
-struct CodeLocation {
- CodeLocation(const std::string& a_file, int a_line)
- : file(a_file), line(a_line) {}
-
- std::string file;
- int line;
-};
-
-// Helper to identify which setup function for TestCase / TestSuite to call.
-// Only one function is allowed, either TestCase or TestSute but not both.
-
-// Utility functions to help SuiteApiResolver
-using SetUpTearDownSuiteFuncType = void (*)();
-
-inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull(
- SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) {
- return a == def ? nullptr : a;
-}
-
-template <typename T>
-// Note that SuiteApiResolver inherits from T because
-// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way
-// SuiteApiResolver can access them.
-struct SuiteApiResolver : T {
- // testing::Test is only forward declared at this point. So we make it a
- // dependend class for the compiler to be OK with it.
- using Test =
- typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
-
- static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
- int line_num) {
- SetUpTearDownSuiteFuncType test_case_fp =
- GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
- SetUpTearDownSuiteFuncType test_suite_fp =
- GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite);
-
- GTEST_CHECK_(!test_case_fp || !test_suite_fp)
- << "Test can not provide both SetUpTestSuite and SetUpTestCase, please "
- "make sure there is only one present at "
- << filename << ":" << line_num;
-
- return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
- }
-
- static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
- int line_num) {
- SetUpTearDownSuiteFuncType test_case_fp =
- GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
- SetUpTearDownSuiteFuncType test_suite_fp =
- GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite);
-
- GTEST_CHECK_(!test_case_fp || !test_suite_fp)
- << "Test can not provide both TearDownTestSuite and TearDownTestCase,"
- " please make sure there is only one present at"
- << filename << ":" << line_num;
-
- return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
- }
-};
-
-// Creates a new TestInfo object and registers it with Google Test;
-// returns the created object.
-//
-// Arguments:
-//
-// test_suite_name: name of the test suite
-// name: name of the test
-// type_param the name of the test's type parameter, or NULL if
-// this is not a typed or a type-parameterized test.
-// value_param text representation of the test's value parameter,
-// or NULL if this is not a type-parameterized test.
-// code_location: code location where the test is defined
-// fixture_class_id: ID of the test fixture class
-// set_up_tc: pointer to the function that sets up the test suite
-// tear_down_tc: pointer to the function that tears down the test suite
-// factory: pointer to the factory that creates a test object.
-// The newly created TestInfo instance will assume
-// ownership of the factory object.
-GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
- const char* test_suite_name, const char* name, const char* type_param,
- const char* value_param, CodeLocation code_location,
- TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
- TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
-
-// If *pstr starts with the given prefix, modifies *pstr to be right
-// past the prefix and returns true; otherwise leaves *pstr unchanged
-// and returns false. None of pstr, *pstr, and prefix can be NULL.
-GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
-
-#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-// State of the definition of a type-parameterized test suite.
-class GTEST_API_ TypedTestSuitePState {
- public:
- TypedTestSuitePState() : registered_(false) {}
-
- // Adds the given test name to defined_test_names_ and return true
- // if the test suite hasn't been registered; otherwise aborts the
- // program.
- bool AddTestName(const char* file, int line, const char* case_name,
- const char* test_name) {
- if (registered_) {
- fprintf(stderr,
- "%s Test %s must be defined before "
- "REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n",
- FormatFileLocation(file, line).c_str(), test_name, case_name);
- fflush(stderr);
- posix::Abort();
- }
- registered_tests_.insert(
- ::std::make_pair(test_name, CodeLocation(file, line)));
- return true;
- }
-
- bool TestExists(const std::string& test_name) const {
- return registered_tests_.count(test_name) > 0;
- }
-
- const CodeLocation& GetCodeLocation(const std::string& test_name) const {
- RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name);
- GTEST_CHECK_(it != registered_tests_.end());
- return it->second;
- }
-
- // Verifies that registered_tests match the test names in
- // defined_test_names_; returns registered_tests if successful, or
- // aborts the program otherwise.
- const char* VerifyRegisteredTestNames(
- const char* file, int line, const char* registered_tests);
-
- private:
- typedef ::std::map<std::string, CodeLocation> RegisteredTestsMap;
-
- bool registered_;
- RegisteredTestsMap registered_tests_;
-};
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-using TypedTestCasePState = TypedTestSuitePState;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-// Skips to the first non-space char after the first comma in 'str';
-// returns NULL if no comma is found in 'str'.
-inline const char* SkipComma(const char* str) {
- const char* comma = strchr(str, ',');
- if (comma == nullptr) {
- return nullptr;
- }
- while (IsSpace(*(++comma))) {}
- return comma;
-}
-
-// Returns the prefix of 'str' before the first comma in it; returns
-// the entire string if it contains no comma.
-inline std::string GetPrefixUntilComma(const char* str) {
- const char* comma = strchr(str, ',');
- return comma == nullptr ? str : std::string(str, comma);
-}
-
-// Splits a given string on a given delimiter, populating a given
-// vector with the fields.
-void SplitString(const ::std::string& str, char delimiter,
- ::std::vector< ::std::string>* dest);
-
-// The default argument to the template below for the case when the user does
-// not provide a name generator.
-struct DefaultNameGenerator {
- template <typename T>
- static std::string GetName(int i) {
- return StreamableToString(i);
- }
-};
-
-template <typename Provided = DefaultNameGenerator>
-struct NameGeneratorSelector {
- typedef Provided type;
-};
-
-template <typename NameGenerator>
-void GenerateNamesRecursively(Types0, std::vector<std::string>*, int) {}
-
-template <typename NameGenerator, typename Types>
-void GenerateNamesRecursively(Types, std::vector<std::string>* result, int i) {
- result->push_back(NameGenerator::template GetName<typename Types::Head>(i));
- GenerateNamesRecursively<NameGenerator>(typename Types::Tail(), result,
- i + 1);
-}
-
-template <typename NameGenerator, typename Types>
-std::vector<std::string> GenerateNames() {
- std::vector<std::string> result;
- GenerateNamesRecursively<NameGenerator>(Types(), &result, 0);
- return result;
-}
-
-// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
-// registers a list of type-parameterized tests with Google Test. The
-// return value is insignificant - we just need to return something
-// such that we can call this function in a namespace scope.
-//
-// Implementation note: The GTEST_TEMPLATE_ macro declares a template
-// template parameter. It's defined in gtest-type-util.h.
-template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
-class TypeParameterizedTest {
- public:
- // 'index' is the index of the test in the type list 'Types'
- // specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
- // Types). Valid values for 'index' are [0, N - 1] where N is the
- // length of Types.
- static bool Register(const char* prefix, const CodeLocation& code_location,
- const char* case_name, const char* test_names, int index,
- const std::vector<std::string>& type_names =
- GenerateNames<DefaultNameGenerator, Types>()) {
- typedef typename Types::Head Type;
- typedef Fixture<Type> FixtureClass;
- typedef typename GTEST_BIND_(TestSel, Type) TestClass;
-
- // First, registers the first type-parameterized test in the type
- // list.
- MakeAndRegisterTestInfo(
- (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
- "/" + type_names[static_cast<size_t>(index)])
- .c_str(),
- StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
- GetTypeName<Type>().c_str(),
- nullptr, // No value parameter.
- code_location, GetTypeId<FixtureClass>(),
- SuiteApiResolver<TestClass>::GetSetUpCaseOrSuite(
- code_location.file.c_str(), code_location.line),
- SuiteApiResolver<TestClass>::GetTearDownCaseOrSuite(
- code_location.file.c_str(), code_location.line),
- new TestFactoryImpl<TestClass>);
-
- // Next, recurses (at compile time) with the tail of the type list.
- return TypeParameterizedTest<Fixture, TestSel,
- typename Types::Tail>::Register(prefix,
- code_location,
- case_name,
- test_names,
- index + 1,
- type_names);
- }
-};
-
-// The base case for the compile time recursion.
-template <GTEST_TEMPLATE_ Fixture, class TestSel>
-class TypeParameterizedTest<Fixture, TestSel, Types0> {
- public:
- static bool Register(const char* /*prefix*/, const CodeLocation&,
- const char* /*case_name*/, const char* /*test_names*/,
- int /*index*/,
- const std::vector<std::string>& =
- std::vector<std::string>() /*type_names*/) {
- return true;
- }
-};
-
-// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register()
-// registers *all combinations* of 'Tests' and 'Types' with Google
-// Test. The return value is insignificant - we just need to return
-// something such that we can call this function in a namespace scope.
-template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
-class TypeParameterizedTestSuite {
- public:
- static bool Register(const char* prefix, CodeLocation code_location,
- const TypedTestSuitePState* state, const char* case_name,
- const char* test_names,
- const std::vector<std::string>& type_names =
- GenerateNames<DefaultNameGenerator, Types>()) {
- std::string test_name = StripTrailingSpaces(
- GetPrefixUntilComma(test_names));
- if (!state->TestExists(test_name)) {
- fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
- case_name, test_name.c_str(),
- FormatFileLocation(code_location.file.c_str(),
- code_location.line).c_str());
- fflush(stderr);
- posix::Abort();
- }
- const CodeLocation& test_location = state->GetCodeLocation(test_name);
-
- typedef typename Tests::Head Head;
-
- // First, register the first test in 'Test' for each type in 'Types'.
- TypeParameterizedTest<Fixture, Head, Types>::Register(
- prefix, test_location, case_name, test_names, 0, type_names);
-
- // Next, recurses (at compile time) with the tail of the test list.
- return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
- Types>::Register(prefix, code_location,
- state, case_name,
- SkipComma(test_names),
- type_names);
- }
-};
-
-// The base case for the compile time recursion.
-template <GTEST_TEMPLATE_ Fixture, typename Types>
-class TypeParameterizedTestSuite<Fixture, Templates0, Types> {
- public:
- static bool Register(const char* /*prefix*/, const CodeLocation&,
- const TypedTestSuitePState* /*state*/,
- const char* /*case_name*/, const char* /*test_names*/,
- const std::vector<std::string>& =
- std::vector<std::string>() /*type_names*/) {
- return true;
- }
-};
-
-#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
-// Returns the current OS stack trace as an std::string.
-//
-// The maximum number of stack frames to be included is specified by
-// the gtest_stack_trace_depth flag. The skip_count parameter
-// specifies the number of top frames to be skipped, which doesn't
-// count against the number of frames to be included.
-//
-// For example, if Foo() calls Bar(), which in turn calls
-// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
-// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
-GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
- UnitTest* unit_test, int skip_count);
-
-// Helpers for suppressing warnings on unreachable code or constant
-// condition.
-
-// Always returns true.
-GTEST_API_ bool AlwaysTrue();
-
-// Always returns false.
-inline bool AlwaysFalse() { return !AlwaysTrue(); }
-
-// Helper for suppressing false warning from Clang on a const char*
-// variable declared in a conditional expression always being NULL in
-// the else branch.
-struct GTEST_API_ ConstCharPtr {
- ConstCharPtr(const char* str) : value(str) {}
- operator bool() const { return true; }
- const char* value;
-};
-
-// A simple Linear Congruential Generator for generating random
-// numbers with a uniform distribution. Unlike rand() and srand(), it
-// doesn't use global state (and therefore can't interfere with user
-// code). Unlike rand_r(), it's portable. An LCG isn't very random,
-// but it's good enough for our purposes.
-class GTEST_API_ Random {
- public:
- static const UInt32 kMaxRange = 1u << 31;
-
- explicit Random(UInt32 seed) : state_(seed) {}
-
- void Reseed(UInt32 seed) { state_ = seed; }
-
- // Generates a random number from [0, range). Crashes if 'range' is
- // 0 or greater than kMaxRange.
- UInt32 Generate(UInt32 range);
-
- private:
- UInt32 state_;
- GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
-};
-
-// Turns const U&, U&, const U, and U all into U.
-#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
- typename std::remove_const<typename std::remove_reference<T>::type>::type
-
-// IsAProtocolMessage<T>::value is a compile-time bool constant that's
-// true if and only if T is type proto2::Message or a subclass of it.
-template <typename T>
-struct IsAProtocolMessage
- : public bool_constant<
- std::is_convertible<const T*, const ::proto2::Message*>::value> {};
-
-// When the compiler sees expression IsContainerTest<C>(0), if C is an
-// STL-style container class, the first overload of IsContainerTest
-// will be viable (since both C::iterator* and C::const_iterator* are
-// valid types and NULL can be implicitly converted to them). It will
-// be picked over the second overload as 'int' is a perfect match for
-// the type of argument 0. If C::iterator or C::const_iterator is not
-// a valid type, the first overload is not viable, and the second
-// overload will be picked. Therefore, we can determine whether C is
-// a container class by checking the type of IsContainerTest<C>(0).
-// The value of the expression is insignificant.
-//
-// In C++11 mode we check the existence of a const_iterator and that an
-// iterator is properly implemented for the container.
-//
-// For pre-C++11 that we look for both C::iterator and C::const_iterator.
-// The reason is that C++ injects the name of a class as a member of the
-// class itself (e.g. you can refer to class iterator as either
-// 'iterator' or 'iterator::iterator'). If we look for C::iterator
-// only, for example, we would mistakenly think that a class named
-// iterator is an STL container.
-//
-// Also note that the simpler approach of overloading
-// IsContainerTest(typename C::const_iterator*) and
-// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
-typedef int IsContainer;
-template <class C,
- class Iterator = decltype(::std::declval<const C&>().begin()),
- class = decltype(::std::declval<const C&>().end()),
- class = decltype(++::std::declval<Iterator&>()),
- class = decltype(*::std::declval<Iterator>()),
- class = typename C::const_iterator>
-IsContainer IsContainerTest(int /* dummy */) {
- return 0;
-}
-
-typedef char IsNotContainer;
-template <class C>
-IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
-
-// Trait to detect whether a type T is a hash table.
-// The heuristic used is that the type contains an inner type `hasher` and does
-// not contain an inner type `reverse_iterator`.
-// If the container is iterable in reverse, then order might actually matter.
-template <typename T>
-struct IsHashTable {
- private:
- template <typename U>
- static char test(typename U::hasher*, typename U::reverse_iterator*);
- template <typename U>
- static int test(typename U::hasher*, ...);
- template <typename U>
- static char test(...);
-
- public:
- static const bool value = sizeof(test<T>(nullptr, nullptr)) == sizeof(int);
-};
-
-template <typename T>
-const bool IsHashTable<T>::value;
-
-template <typename C,
- bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
-struct IsRecursiveContainerImpl;
-
-template <typename C>
-struct IsRecursiveContainerImpl<C, false> : public std::false_type {};
-
-// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
-// obey the same inconsistencies as the IsContainerTest, namely check if
-// something is a container is relying on only const_iterator in C++11 and
-// is relying on both const_iterator and iterator otherwise
-template <typename C>
-struct IsRecursiveContainerImpl<C, true> {
- using value_type = decltype(*std::declval<typename C::const_iterator>());
- using type =
- std::is_same<typename std::remove_const<
- typename std::remove_reference<value_type>::type>::type,
- C>;
-};
-
-// IsRecursiveContainer<Type> is a unary compile-time predicate that
-// evaluates whether C is a recursive container type. A recursive container
-// type is a container type whose value_type is equal to the container type
-// itself. An example for a recursive container type is
-// boost::filesystem::path, whose iterator has a value_type that is equal to
-// boost::filesystem::path.
-template <typename C>
-struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
-
-// Utilities for native arrays.
-
-// ArrayEq() compares two k-dimensional native arrays using the
-// elements' operator==, where k can be any integer >= 0. When k is
-// 0, ArrayEq() degenerates into comparing a single pair of values.
-
-template <typename T, typename U>
-bool ArrayEq(const T* lhs, size_t size, const U* rhs);
-
-// This generic version is used when k is 0.
-template <typename T, typename U>
-inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
-
-// This overload is used when k >= 1.
-template <typename T, typename U, size_t N>
-inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
- return internal::ArrayEq(lhs, N, rhs);
-}
-
-// This helper reduces code bloat. If we instead put its logic inside
-// the previous ArrayEq() function, arrays with different sizes would
-// lead to different copies of the template code.
-template <typename T, typename U>
-bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
- for (size_t i = 0; i != size; i++) {
- if (!internal::ArrayEq(lhs[i], rhs[i]))
- return false;
- }
- return true;
-}
-
-// Finds the first element in the iterator range [begin, end) that
-// equals elem. Element may be a native array type itself.
-template <typename Iter, typename Element>
-Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
- for (Iter it = begin; it != end; ++it) {
- if (internal::ArrayEq(*it, elem))
- return it;
- }
- return end;
-}
-
-// CopyArray() copies a k-dimensional native array using the elements'
-// operator=, where k can be any integer >= 0. When k is 0,
-// CopyArray() degenerates into copying a single value.
-
-template <typename T, typename U>
-void CopyArray(const T* from, size_t size, U* to);
-
-// This generic version is used when k is 0.
-template <typename T, typename U>
-inline void CopyArray(const T& from, U* to) { *to = from; }
-
-// This overload is used when k >= 1.
-template <typename T, typename U, size_t N>
-inline void CopyArray(const T(&from)[N], U(*to)[N]) {
- internal::CopyArray(from, N, *to);
-}
-
-// This helper reduces code bloat. If we instead put its logic inside
-// the previous CopyArray() function, arrays with different sizes
-// would lead to different copies of the template code.
-template <typename T, typename U>
-void CopyArray(const T* from, size_t size, U* to) {
- for (size_t i = 0; i != size; i++) {
- internal::CopyArray(from[i], to + i);
- }
-}
-
-// The relation between an NativeArray object (see below) and the
-// native array it represents.
-// We use 2 different structs to allow non-copyable types to be used, as long
-// as RelationToSourceReference() is passed.
-struct RelationToSourceReference {};
-struct RelationToSourceCopy {};
-
-// Adapts a native array to a read-only STL-style container. Instead
-// of the complete STL container concept, this adaptor only implements
-// members useful for Google Mock's container matchers. New members
-// should be added as needed. To simplify the implementation, we only
-// support Element being a raw type (i.e. having no top-level const or
-// reference modifier). It's the client's responsibility to satisfy
-// this requirement. Element can be an array type itself (hence
-// multi-dimensional arrays are supported).
-template <typename Element>
-class NativeArray {
- public:
- // STL-style container typedefs.
- typedef Element value_type;
- typedef Element* iterator;
- typedef const Element* const_iterator;
-
- // Constructs from a native array. References the source.
- NativeArray(const Element* array, size_t count, RelationToSourceReference) {
- InitRef(array, count);
- }
-
- // Constructs from a native array. Copies the source.
- NativeArray(const Element* array, size_t count, RelationToSourceCopy) {
- InitCopy(array, count);
- }
-
- // Copy constructor.
- NativeArray(const NativeArray& rhs) {
- (this->*rhs.clone_)(rhs.array_, rhs.size_);
- }
-
- ~NativeArray() {
- if (clone_ != &NativeArray::InitRef)
- delete[] array_;
- }
-
- // STL-style container methods.
- size_t size() const { return size_; }
- const_iterator begin() const { return array_; }
- const_iterator end() const { return array_ + size_; }
- bool operator==(const NativeArray& rhs) const {
- return size() == rhs.size() &&
- ArrayEq(begin(), size(), rhs.begin());
- }
-
- private:
- static_assert(!std::is_const<Element>::value, "Type must not be const");
- static_assert(!std::is_reference<Element>::value,
- "Type must not be a reference");
-
- // Initializes this object with a copy of the input.
- void InitCopy(const Element* array, size_t a_size) {
- Element* const copy = new Element[a_size];
- CopyArray(array, a_size, copy);
- array_ = copy;
- size_ = a_size;
- clone_ = &NativeArray::InitCopy;
- }
-
- // Initializes this object with a reference of the input.
- void InitRef(const Element* array, size_t a_size) {
- array_ = array;
- size_ = a_size;
- clone_ = &NativeArray::InitRef;
- }
-
- const Element* array_;
- size_t size_;
- void (NativeArray::*clone_)(const Element*, size_t);
-
- GTEST_DISALLOW_ASSIGN_(NativeArray);
-};
-
-// Backport of std::index_sequence.
-template <size_t... Is>
-struct IndexSequence {
- using type = IndexSequence;
-};
-
-// Double the IndexSequence, and one if plus_one is true.
-template <bool plus_one, typename T, size_t sizeofT>
-struct DoubleSequence;
-template <size_t... I, size_t sizeofT>
-struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
- using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
-};
-template <size_t... I, size_t sizeofT>
-struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
- using type = IndexSequence<I..., (sizeofT + I)...>;
-};
-
-// Backport of std::make_index_sequence.
-// It uses O(ln(N)) instantiation depth.
-template <size_t N>
-struct MakeIndexSequence
- : DoubleSequence<N % 2 == 1, typename MakeIndexSequence<N / 2>::type,
- N / 2>::type {};
-
-template <>
-struct MakeIndexSequence<0> : IndexSequence<> {};
-
-// FIXME: This implementation of ElemFromList is O(1) in instantiation depth,
-// but it is O(N^2) in total instantiations. Not sure if this is the best
-// tradeoff, as it will make it somewhat slow to compile.
-template <typename T, size_t, size_t>
-struct ElemFromListImpl {};
-
-template <typename T, size_t I>
-struct ElemFromListImpl<T, I, I> {
- using type = T;
-};
-
-// Get the Nth element from T...
-// It uses O(1) instantiation depth.
-template <size_t N, typename I, typename... T>
-struct ElemFromList;
-
-template <size_t N, size_t... I, typename... T>
-struct ElemFromList<N, IndexSequence<I...>, T...>
- : ElemFromListImpl<T, N, I>... {};
-
-template <typename... T>
-class FlatTuple;
-
-template <typename Derived, size_t I>
-struct FlatTupleElemBase;
-
-template <typename... T, size_t I>
-struct FlatTupleElemBase<FlatTuple<T...>, I> {
- using value_type =
- typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
- T...>::type;
- FlatTupleElemBase() = default;
- explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
- value_type value;
-};
-
-template <typename Derived, typename Idx>
-struct FlatTupleBase;
-
-template <size_t... Idx, typename... T>
-struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
- : FlatTupleElemBase<FlatTuple<T...>, Idx>... {
- using Indices = IndexSequence<Idx...>;
- FlatTupleBase() = default;
- explicit FlatTupleBase(T... t)
- : FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {}
-};
-
-// Analog to std::tuple but with different tradeoffs.
-// This class minimizes the template instantiation depth, thus allowing more
-// elements that std::tuple would. std::tuple has been seen to require an
-// instantiation depth of more than 10x the number of elements in some
-// implementations.
-// FlatTuple and ElemFromList are not recursive and have a fixed depth
-// regardless of T...
-// MakeIndexSequence, on the other hand, it is recursive but with an
-// instantiation depth of O(ln(N)).
-template <typename... T>
-class FlatTuple
- : private FlatTupleBase<FlatTuple<T...>,
- typename MakeIndexSequence<sizeof...(T)>::type> {
- using Indices = typename FlatTuple::FlatTupleBase::Indices;
-
- public:
- FlatTuple() = default;
- explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
-
- template <size_t I>
- const typename ElemFromList<I, Indices, T...>::type& Get() const {
- return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
- }
-
- template <size_t I>
- typename ElemFromList<I, Indices, T...>::type& Get() {
- return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
- }
-};
-
-// Utility functions to be called with static_assert to induce deprecation
-// warnings.
-GTEST_INTERNAL_DEPRECATED(
- "INSTANTIATE_TEST_CASE_P is deprecated, please use "
- "INSTANTIATE_TEST_SUITE_P")
-constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
-
-GTEST_INTERNAL_DEPRECATED(
- "TYPED_TEST_CASE_P is deprecated, please use "
- "TYPED_TEST_SUITE_P")
-constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
-
-GTEST_INTERNAL_DEPRECATED(
- "TYPED_TEST_CASE is deprecated, please use "
- "TYPED_TEST_SUITE")
-constexpr bool TypedTestCaseIsDeprecated() { return true; }
-
-GTEST_INTERNAL_DEPRECATED(
- "REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
- "REGISTER_TYPED_TEST_SUITE_P")
-constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
-
-GTEST_INTERNAL_DEPRECATED(
- "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
- "INSTANTIATE_TYPED_TEST_SUITE_P")
-constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
-
-} // namespace internal
-} // namespace testing
-
-#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
- ::testing::internal::AssertHelper(result_type, file, line, message) \
- = ::testing::Message()
-
-#define GTEST_MESSAGE_(message, result_type) \
- GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
-
-#define GTEST_FATAL_FAILURE_(message) \
- return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
-
-#define GTEST_NONFATAL_FAILURE_(message) \
- GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
-
-#define GTEST_SUCCESS_(message) \
- GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
-
-#define GTEST_SKIP_(message) \
- return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)
-
-// Suppress MSVC warning 4072 (unreachable code) for the code following
-// statement if it returns or throws (or doesn't return or throw in some
-// situations).
-#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
- if (::testing::internal::AlwaysTrue()) { statement; }
-
-#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::ConstCharPtr gtest_msg = "") { \
- bool gtest_caught_expected = false; \
- try { \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- } \
- catch (expected_exception const&) { \
- gtest_caught_expected = true; \
- } \
- catch (...) { \
- gtest_msg.value = \
- "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws a different type."; \
- goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
- } \
- if (!gtest_caught_expected) { \
- gtest_msg.value = \
- "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws nothing."; \
- goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
- } \
- } else \
- GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
- fail(gtest_msg.value)
-
-#define GTEST_TEST_NO_THROW_(statement, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::AlwaysTrue()) { \
- try { \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- } \
- catch (...) { \
- goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
- } \
- } else \
- GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
- fail("Expected: " #statement " doesn't throw an exception.\n" \
- " Actual: it throws.")
-
-#define GTEST_TEST_ANY_THROW_(statement, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::AlwaysTrue()) { \
- bool gtest_caught_any = false; \
- try { \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- } \
- catch (...) { \
- gtest_caught_any = true; \
- } \
- if (!gtest_caught_any) { \
- goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
- } \
- } else \
- GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
- fail("Expected: " #statement " throws an exception.\n" \
- " Actual: it doesn't.")
-
-
-// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
-// either a boolean expression or an AssertionResult. text is a textual
-// represenation of expression as it was passed into the EXPECT_TRUE.
-#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const ::testing::AssertionResult gtest_ar_ = \
- ::testing::AssertionResult(expression)) \
- ; \
- else \
- fail(::testing::internal::GetBoolAssertionFailureMessage(\
- gtest_ar_, text, #actual, #expected).c_str())
-
-#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::AlwaysTrue()) { \
- ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
- if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
- goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
- } \
- } else \
- GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
- fail("Expected: " #statement " doesn't generate new fatal " \
- "failures in the current thread.\n" \
- " Actual: it does.")
-
-// Expands to the name of the class that implements the given test.
-#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
- test_suite_name##_##test_name##_Test
-
-// Helper macro for defining tests.
-#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \
- static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \
- "test_suite_name must not be empty"); \
- static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \
- "test_name must not be empty"); \
- class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
- : public parent_class { \
- public: \
- GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
- \
- private: \
- virtual void TestBody(); \
- static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
- GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
- test_name)); \
- }; \
- \
- ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
- test_name)::test_info_ = \
- ::testing::internal::MakeAndRegisterTestInfo( \
- #test_suite_name, #test_name, nullptr, nullptr, \
- ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
- ::testing::internal::SuiteApiResolver< \
- parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \
- ::testing::internal::SuiteApiResolver< \
- parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \
- new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \
- test_suite_name, test_name)>); \
- void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Type and function utilities for implementing parameterized tests.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
-
-#include <ctype.h>
-
-#include <cassert>
-#include <iterator>
-#include <memory>
-#include <set>
-#include <tuple>
-#include <utility>
-#include <vector>
-
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-port.h"
-#include "gtest/gtest-printers.h"
-
-namespace testing {
-// Input to a parameterized test name generator, describing a test parameter.
-// Consists of the parameter value and the integer parameter index.
-template <class ParamType>
-struct TestParamInfo {
- TestParamInfo(const ParamType& a_param, size_t an_index) :
- param(a_param),
- index(an_index) {}
- ParamType param;
- size_t index;
-};
-
-// A builtin parameterized test name generator which returns the result of
-// testing::PrintToString.
-struct PrintToStringParamName {
- template <class ParamType>
- std::string operator()(const TestParamInfo<ParamType>& info) const {
- return PrintToString(info.param);
- }
-};
-
-namespace internal {
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-// Utility Functions
-
-// Outputs a message explaining invalid registration of different
-// fixture class for the same test suite. This may happen when
-// TEST_P macro is used to define two tests with the same name
-// but in different namespaces.
-GTEST_API_ void ReportInvalidTestSuiteType(const char* test_suite_name,
- CodeLocation code_location);
-
-template <typename> class ParamGeneratorInterface;
-template <typename> class ParamGenerator;
-
-// Interface for iterating over elements provided by an implementation
-// of ParamGeneratorInterface<T>.
-template <typename T>
-class ParamIteratorInterface {
- public:
- virtual ~ParamIteratorInterface() {}
- // A pointer to the base generator instance.
- // Used only for the purposes of iterator comparison
- // to make sure that two iterators belong to the same generator.
- virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
- // Advances iterator to point to the next element
- // provided by the generator. The caller is responsible
- // for not calling Advance() on an iterator equal to
- // BaseGenerator()->End().
- virtual void Advance() = 0;
- // Clones the iterator object. Used for implementing copy semantics
- // of ParamIterator<T>.
- virtual ParamIteratorInterface* Clone() const = 0;
- // Dereferences the current iterator and provides (read-only) access
- // to the pointed value. It is the caller's responsibility not to call
- // Current() on an iterator equal to BaseGenerator()->End().
- // Used for implementing ParamGenerator<T>::operator*().
- virtual const T* Current() const = 0;
- // Determines whether the given iterator and other point to the same
- // element in the sequence generated by the generator.
- // Used for implementing ParamGenerator<T>::operator==().
- virtual bool Equals(const ParamIteratorInterface& other) const = 0;
-};
-
-// Class iterating over elements provided by an implementation of
-// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
-// and implements the const forward iterator concept.
-template <typename T>
-class ParamIterator {
- public:
- typedef T value_type;
- typedef const T& reference;
- typedef ptrdiff_t difference_type;
-
- // ParamIterator assumes ownership of the impl_ pointer.
- ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
- ParamIterator& operator=(const ParamIterator& other) {
- if (this != &other)
- impl_.reset(other.impl_->Clone());
- return *this;
- }
-
- const T& operator*() const { return *impl_->Current(); }
- const T* operator->() const { return impl_->Current(); }
- // Prefix version of operator++.
- ParamIterator& operator++() {
- impl_->Advance();
- return *this;
- }
- // Postfix version of operator++.
- ParamIterator operator++(int /*unused*/) {
- ParamIteratorInterface<T>* clone = impl_->Clone();
- impl_->Advance();
- return ParamIterator(clone);
- }
- bool operator==(const ParamIterator& other) const {
- return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
- }
- bool operator!=(const ParamIterator& other) const {
- return !(*this == other);
- }
-
- private:
- friend class ParamGenerator<T>;
- explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
- std::unique_ptr<ParamIteratorInterface<T> > impl_;
-};
-
-// ParamGeneratorInterface<T> is the binary interface to access generators
-// defined in other translation units.
-template <typename T>
-class ParamGeneratorInterface {
- public:
- typedef T ParamType;
-
- virtual ~ParamGeneratorInterface() {}
-
- // Generator interface definition
- virtual ParamIteratorInterface<T>* Begin() const = 0;
- virtual ParamIteratorInterface<T>* End() const = 0;
-};
-
-// Wraps ParamGeneratorInterface<T> and provides general generator syntax
-// compatible with the STL Container concept.
-// This class implements copy initialization semantics and the contained
-// ParamGeneratorInterface<T> instance is shared among all copies
-// of the original object. This is possible because that instance is immutable.
-template<typename T>
-class ParamGenerator {
- public:
- typedef ParamIterator<T> iterator;
-
- explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
- ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
-
- ParamGenerator& operator=(const ParamGenerator& other) {
- impl_ = other.impl_;
- return *this;
- }
-
- iterator begin() const { return iterator(impl_->Begin()); }
- iterator end() const { return iterator(impl_->End()); }
-
- private:
- std::shared_ptr<const ParamGeneratorInterface<T> > impl_;
-};
-
-// Generates values from a range of two comparable values. Can be used to
-// generate sequences of user-defined types that implement operator+() and
-// operator<().
-// This class is used in the Range() function.
-template <typename T, typename IncrementT>
-class RangeGenerator : public ParamGeneratorInterface<T> {
- public:
- RangeGenerator(T begin, T end, IncrementT step)
- : begin_(begin), end_(end),
- step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
- ~RangeGenerator() override {}
-
- ParamIteratorInterface<T>* Begin() const override {
- return new Iterator(this, begin_, 0, step_);
- }
- ParamIteratorInterface<T>* End() const override {
- return new Iterator(this, end_, end_index_, step_);
- }
-
- private:
- class Iterator : public ParamIteratorInterface<T> {
- public:
- Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
- IncrementT step)
- : base_(base), value_(value), index_(index), step_(step) {}
- ~Iterator() override {}
-
- const ParamGeneratorInterface<T>* BaseGenerator() const override {
- return base_;
- }
- void Advance() override {
- value_ = static_cast<T>(value_ + step_);
- index_++;
- }
- ParamIteratorInterface<T>* Clone() const override {
- return new Iterator(*this);
- }
- const T* Current() const override { return &value_; }
- bool Equals(const ParamIteratorInterface<T>& other) const override {
- // Having the same base generator guarantees that the other
- // iterator is of the same type and we can downcast.
- GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
- << "The program attempted to compare iterators "
- << "from different generators." << std::endl;
- const int other_index =
- CheckedDowncastToActualType<const Iterator>(&other)->index_;
- return index_ == other_index;
- }
-
- private:
- Iterator(const Iterator& other)
- : ParamIteratorInterface<T>(),
- base_(other.base_), value_(other.value_), index_(other.index_),
- step_(other.step_) {}
-
- // No implementation - assignment is unsupported.
- void operator=(const Iterator& other);
-
- const ParamGeneratorInterface<T>* const base_;
- T value_;
- int index_;
- const IncrementT step_;
- }; // class RangeGenerator::Iterator
-
- static int CalculateEndIndex(const T& begin,
- const T& end,
- const IncrementT& step) {
- int end_index = 0;
- for (T i = begin; i < end; i = static_cast<T>(i + step))
- end_index++;
- return end_index;
- }
-
- // No implementation - assignment is unsupported.
- void operator=(const RangeGenerator& other);
-
- const T begin_;
- const T end_;
- const IncrementT step_;
- // The index for the end() iterator. All the elements in the generated
- // sequence are indexed (0-based) to aid iterator comparison.
- const int end_index_;
-}; // class RangeGenerator
-
-
-// Generates values from a pair of STL-style iterators. Used in the
-// ValuesIn() function. The elements are copied from the source range
-// since the source can be located on the stack, and the generator
-// is likely to persist beyond that stack frame.
-template <typename T>
-class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
- public:
- template <typename ForwardIterator>
- ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
- : container_(begin, end) {}
- ~ValuesInIteratorRangeGenerator() override {}
-
- ParamIteratorInterface<T>* Begin() const override {
- return new Iterator(this, container_.begin());
- }
- ParamIteratorInterface<T>* End() const override {
- return new Iterator(this, container_.end());
- }
-
- private:
- typedef typename ::std::vector<T> ContainerType;
-
- class Iterator : public ParamIteratorInterface<T> {
- public:
- Iterator(const ParamGeneratorInterface<T>* base,
- typename ContainerType::const_iterator iterator)
- : base_(base), iterator_(iterator) {}
- ~Iterator() override {}
-
- const ParamGeneratorInterface<T>* BaseGenerator() const override {
- return base_;
- }
- void Advance() override {
- ++iterator_;
- value_.reset();
- }
- ParamIteratorInterface<T>* Clone() const override {
- return new Iterator(*this);
- }
- // We need to use cached value referenced by iterator_ because *iterator_
- // can return a temporary object (and of type other then T), so just
- // having "return &*iterator_;" doesn't work.
- // value_ is updated here and not in Advance() because Advance()
- // can advance iterator_ beyond the end of the range, and we cannot
- // detect that fact. The client code, on the other hand, is
- // responsible for not calling Current() on an out-of-range iterator.
- const T* Current() const override {
- if (value_.get() == nullptr) value_.reset(new T(*iterator_));
- return value_.get();
- }
- bool Equals(const ParamIteratorInterface<T>& other) const override {
- // Having the same base generator guarantees that the other
- // iterator is of the same type and we can downcast.
- GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
- << "The program attempted to compare iterators "
- << "from different generators." << std::endl;
- return iterator_ ==
- CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
- }
-
- private:
- Iterator(const Iterator& other)
- // The explicit constructor call suppresses a false warning
- // emitted by gcc when supplied with the -Wextra option.
- : ParamIteratorInterface<T>(),
- base_(other.base_),
- iterator_(other.iterator_) {}
-
- const ParamGeneratorInterface<T>* const base_;
- typename ContainerType::const_iterator iterator_;
- // A cached value of *iterator_. We keep it here to allow access by
- // pointer in the wrapping iterator's operator->().
- // value_ needs to be mutable to be accessed in Current().
- // Use of std::unique_ptr helps manage cached value's lifetime,
- // which is bound by the lifespan of the iterator itself.
- mutable std::unique_ptr<const T> value_;
- }; // class ValuesInIteratorRangeGenerator::Iterator
-
- // No implementation - assignment is unsupported.
- void operator=(const ValuesInIteratorRangeGenerator& other);
-
- const ContainerType container_;
-}; // class ValuesInIteratorRangeGenerator
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// Default parameterized test name generator, returns a string containing the
-// integer test parameter index.
-template <class ParamType>
-std::string DefaultParamName(const TestParamInfo<ParamType>& info) {
- Message name_stream;
- name_stream << info.index;
- return name_stream.GetString();
-}
-
-template <typename T = int>
-void TestNotEmpty() {
- static_assert(sizeof(T) == 0, "Empty arguments are not allowed.");
-}
-template <typename T = int>
-void TestNotEmpty(const T&) {}
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// Stores a parameter value and later creates tests parameterized with that
-// value.
-template <class TestClass>
-class ParameterizedTestFactory : public TestFactoryBase {
- public:
- typedef typename TestClass::ParamType ParamType;
- explicit ParameterizedTestFactory(ParamType parameter) :
- parameter_(parameter) {}
- Test* CreateTest() override {
- TestClass::SetParam(¶meter_);
- return new TestClass();
- }
-
- private:
- const ParamType parameter_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
-};
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// TestMetaFactoryBase is a base class for meta-factories that create
-// test factories for passing into MakeAndRegisterTestInfo function.
-template <class ParamType>
-class TestMetaFactoryBase {
- public:
- virtual ~TestMetaFactoryBase() {}
-
- virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
-};
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// TestMetaFactory creates test factories for passing into
-// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
-// ownership of test factory pointer, same factory object cannot be passed
-// into that method twice. But ParameterizedTestSuiteInfo is going to call
-// it for each Test/Parameter value combination. Thus it needs meta factory
-// creator class.
-template <class TestSuite>
-class TestMetaFactory
- : public TestMetaFactoryBase<typename TestSuite::ParamType> {
- public:
- using ParamType = typename TestSuite::ParamType;
-
- TestMetaFactory() {}
-
- TestFactoryBase* CreateTestFactory(ParamType parameter) override {
- return new ParameterizedTestFactory<TestSuite>(parameter);
- }
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
-};
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// ParameterizedTestSuiteInfoBase is a generic interface
-// to ParameterizedTestSuiteInfo classes. ParameterizedTestSuiteInfoBase
-// accumulates test information provided by TEST_P macro invocations
-// and generators provided by INSTANTIATE_TEST_SUITE_P macro invocations
-// and uses that information to register all resulting test instances
-// in RegisterTests method. The ParameterizeTestSuiteRegistry class holds
-// a collection of pointers to the ParameterizedTestSuiteInfo objects
-// and calls RegisterTests() on each of them when asked.
-class ParameterizedTestSuiteInfoBase {
- public:
- virtual ~ParameterizedTestSuiteInfoBase() {}
-
- // Base part of test suite name for display purposes.
- virtual const std::string& GetTestSuiteName() const = 0;
- // Test case id to verify identity.
- virtual TypeId GetTestSuiteTypeId() const = 0;
- // UnitTest class invokes this method to register tests in this
- // test suite right before running them in RUN_ALL_TESTS macro.
- // This method should not be called more than once on any single
- // instance of a ParameterizedTestSuiteInfoBase derived class.
- virtual void RegisterTests() = 0;
-
- protected:
- ParameterizedTestSuiteInfoBase() {}
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
-};
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P
-// macro invocations for a particular test suite and generators
-// obtained from INSTANTIATE_TEST_SUITE_P macro invocations for that
-// test suite. It registers tests with all values generated by all
-// generators when asked.
-template <class TestSuite>
-class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase {
- public:
- // ParamType and GeneratorCreationFunc are private types but are required
- // for declarations of public methods AddTestPattern() and
- // AddTestSuiteInstantiation().
- using ParamType = typename TestSuite::ParamType;
- // A function that returns an instance of appropriate generator type.
- typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
- using ParamNameGeneratorFunc = std::string(const TestParamInfo<ParamType>&);
-
- explicit ParameterizedTestSuiteInfo(const char* name,
- CodeLocation code_location)
- : test_suite_name_(name), code_location_(code_location) {}
-
- // Test case base name for display purposes.
- const std::string& GetTestSuiteName() const override {
- return test_suite_name_;
- }
- // Test case id to verify identity.
- TypeId GetTestSuiteTypeId() const override { return GetTypeId<TestSuite>(); }
- // TEST_P macro uses AddTestPattern() to record information
- // about a single test in a LocalTestInfo structure.
- // test_suite_name is the base name of the test suite (without invocation
- // prefix). test_base_name is the name of an individual test without
- // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
- // test suite base name and DoBar is test base name.
- void AddTestPattern(const char* test_suite_name, const char* test_base_name,
- TestMetaFactoryBase<ParamType>* meta_factory) {
- tests_.push_back(std::shared_ptr<TestInfo>(
- new TestInfo(test_suite_name, test_base_name, meta_factory)));
- }
- // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information
- // about a generator.
- int AddTestSuiteInstantiation(const std::string& instantiation_name,
- GeneratorCreationFunc* func,
- ParamNameGeneratorFunc* name_func,
- const char* file, int line) {
- instantiations_.push_back(
- InstantiationInfo(instantiation_name, func, name_func, file, line));
- return 0; // Return value used only to run this method in namespace scope.
- }
- // UnitTest class invokes this method to register tests in this test suite
- // test suites right before running tests in RUN_ALL_TESTS macro.
- // This method should not be called more than once on any single
- // instance of a ParameterizedTestSuiteInfoBase derived class.
- // UnitTest has a guard to prevent from calling this method more than once.
- void RegisterTests() override {
- for (typename TestInfoContainer::iterator test_it = tests_.begin();
- test_it != tests_.end(); ++test_it) {
- std::shared_ptr<TestInfo> test_info = *test_it;
- for (typename InstantiationContainer::iterator gen_it =
- instantiations_.begin(); gen_it != instantiations_.end();
- ++gen_it) {
- const std::string& instantiation_name = gen_it->name;
- ParamGenerator<ParamType> generator((*gen_it->generator)());
- ParamNameGeneratorFunc* name_func = gen_it->name_func;
- const char* file = gen_it->file;
- int line = gen_it->line;
-
- std::string test_suite_name;
- if ( !instantiation_name.empty() )
- test_suite_name = instantiation_name + "/";
- test_suite_name += test_info->test_suite_base_name;
-
- size_t i = 0;
- std::set<std::string> test_param_names;
- for (typename ParamGenerator<ParamType>::iterator param_it =
- generator.begin();
- param_it != generator.end(); ++param_it, ++i) {
- Message test_name_stream;
-
- std::string param_name = name_func(
- TestParamInfo<ParamType>(*param_it, i));
-
- GTEST_CHECK_(IsValidParamName(param_name))
- << "Parameterized test name '" << param_name
- << "' is invalid, in " << file
- << " line " << line << std::endl;
-
- GTEST_CHECK_(test_param_names.count(param_name) == 0)
- << "Duplicate parameterized test name '" << param_name
- << "', in " << file << " line " << line << std::endl;
-
- test_param_names.insert(param_name);
-
- if (!test_info->test_base_name.empty()) {
- test_name_stream << test_info->test_base_name << "/";
- }
- test_name_stream << param_name;
- MakeAndRegisterTestInfo(
- test_suite_name.c_str(), test_name_stream.GetString().c_str(),
- nullptr, // No type parameter.
- PrintToString(*param_it).c_str(), code_location_,
- GetTestSuiteTypeId(),
- SuiteApiResolver<TestSuite>::GetSetUpCaseOrSuite(file, line),
- SuiteApiResolver<TestSuite>::GetTearDownCaseOrSuite(file, line),
- test_info->test_meta_factory->CreateTestFactory(*param_it));
- } // for param_it
- } // for gen_it
- } // for test_it
- } // RegisterTests
-
- private:
- // LocalTestInfo structure keeps information about a single test registered
- // with TEST_P macro.
- struct TestInfo {
- TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name,
- TestMetaFactoryBase<ParamType>* a_test_meta_factory)
- : test_suite_base_name(a_test_suite_base_name),
- test_base_name(a_test_base_name),
- test_meta_factory(a_test_meta_factory) {}
-
- const std::string test_suite_base_name;
- const std::string test_base_name;
- const std::unique_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
- };
- using TestInfoContainer = ::std::vector<std::shared_ptr<TestInfo> >;
- // Records data received from INSTANTIATE_TEST_SUITE_P macros:
- // <Instantiation name, Sequence generator creation function,
- // Name generator function, Source file, Source line>
- struct InstantiationInfo {
- InstantiationInfo(const std::string &name_in,
- GeneratorCreationFunc* generator_in,
- ParamNameGeneratorFunc* name_func_in,
- const char* file_in,
- int line_in)
- : name(name_in),
- generator(generator_in),
- name_func(name_func_in),
- file(file_in),
- line(line_in) {}
-
- std::string name;
- GeneratorCreationFunc* generator;
- ParamNameGeneratorFunc* name_func;
- const char* file;
- int line;
- };
- typedef ::std::vector<InstantiationInfo> InstantiationContainer;
-
- static bool IsValidParamName(const std::string& name) {
- // Check for empty string
- if (name.empty())
- return false;
-
- // Check for invalid characters
- for (std::string::size_type index = 0; index < name.size(); ++index) {
- if (!isalnum(name[index]) && name[index] != '_')
- return false;
- }
-
- return true;
- }
-
- const std::string test_suite_name_;
- CodeLocation code_location_;
- TestInfoContainer tests_;
- InstantiationContainer instantiations_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfo);
-}; // class ParameterizedTestSuiteInfo
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-template <class TestCase>
-using ParameterizedTestCaseInfo = ParameterizedTestSuiteInfo<TestCase>;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// ParameterizedTestSuiteRegistry contains a map of
-// ParameterizedTestSuiteInfoBase classes accessed by test suite names. TEST_P
-// and INSTANTIATE_TEST_SUITE_P macros use it to locate their corresponding
-// ParameterizedTestSuiteInfo descriptors.
-class ParameterizedTestSuiteRegistry {
- public:
- ParameterizedTestSuiteRegistry() {}
- ~ParameterizedTestSuiteRegistry() {
- for (auto& test_suite_info : test_suite_infos_) {
- delete test_suite_info;
- }
- }
-
- // Looks up or creates and returns a structure containing information about
- // tests and instantiations of a particular test suite.
- template <class TestSuite>
- ParameterizedTestSuiteInfo<TestSuite>* GetTestSuitePatternHolder(
- const char* test_suite_name, CodeLocation code_location) {
- ParameterizedTestSuiteInfo<TestSuite>* typed_test_info = nullptr;
- for (auto& test_suite_info : test_suite_infos_) {
- if (test_suite_info->GetTestSuiteName() == test_suite_name) {
- if (test_suite_info->GetTestSuiteTypeId() != GetTypeId<TestSuite>()) {
- // Complain about incorrect usage of Google Test facilities
- // and terminate the program since we cannot guaranty correct
- // test suite setup and tear-down in this case.
- ReportInvalidTestSuiteType(test_suite_name, code_location);
- posix::Abort();
- } else {
- // At this point we are sure that the object we found is of the same
- // type we are looking for, so we downcast it to that type
- // without further checks.
- typed_test_info = CheckedDowncastToActualType<
- ParameterizedTestSuiteInfo<TestSuite> >(test_suite_info);
- }
- break;
- }
- }
- if (typed_test_info == nullptr) {
- typed_test_info = new ParameterizedTestSuiteInfo<TestSuite>(
- test_suite_name, code_location);
- test_suite_infos_.push_back(typed_test_info);
- }
- return typed_test_info;
- }
- void RegisterTests() {
- for (auto& test_suite_info : test_suite_infos_) {
- test_suite_info->RegisterTests();
- }
- }
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- template <class TestCase>
- ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
- const char* test_case_name, CodeLocation code_location) {
- return GetTestSuitePatternHolder<TestCase>(test_case_name, code_location);
- }
-
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- private:
- using TestSuiteInfoContainer = ::std::vector<ParameterizedTestSuiteInfoBase*>;
-
- TestSuiteInfoContainer test_suite_infos_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry);
-};
-
-} // namespace internal
-
-// Forward declarations of ValuesIn(), which is implemented in
-// include/gtest/gtest-param-test.h.
-template <class Container>
-internal::ParamGenerator<typename Container::value_type> ValuesIn(
- const Container& container);
-
-namespace internal {
-// Used in the Values() function to provide polymorphic capabilities.
-
-template <typename... Ts>
-class ValueArray {
- public:
- ValueArray(Ts... v) : v_{std::move(v)...} {}
-
- template <typename T>
- operator ParamGenerator<T>() const { // NOLINT
- return ValuesIn(MakeVector<T>(MakeIndexSequence<sizeof...(Ts)>()));
- }
-
- private:
- template <typename T, size_t... I>
- std::vector<T> MakeVector(IndexSequence<I...>) const {
- return std::vector<T>{static_cast<T>(v_.template Get<I>())...};
- }
-
- FlatTuple<Ts...> v_;
-};
-
-template <typename... T>
-class CartesianProductGenerator
- : public ParamGeneratorInterface<::std::tuple<T...>> {
- public:
- typedef ::std::tuple<T...> ParamType;
-
- CartesianProductGenerator(const std::tuple<ParamGenerator<T>...>& g)
- : generators_(g) {}
- ~CartesianProductGenerator() override {}
-
- ParamIteratorInterface<ParamType>* Begin() const override {
- return new Iterator(this, generators_, false);
- }
- ParamIteratorInterface<ParamType>* End() const override {
- return new Iterator(this, generators_, true);
- }
-
- private:
- template <class I>
- class IteratorImpl;
- template <size_t... I>
- class IteratorImpl<IndexSequence<I...>>
- : public ParamIteratorInterface<ParamType> {
- public:
- IteratorImpl(const ParamGeneratorInterface<ParamType>* base,
- const std::tuple<ParamGenerator<T>...>& generators, bool is_end)
- : base_(base),
- begin_(std::get<I>(generators).begin()...),
- end_(std::get<I>(generators).end()...),
- current_(is_end ? end_ : begin_) {
- ComputeCurrentValue();
- }
- ~IteratorImpl() override {}
-
- const ParamGeneratorInterface<ParamType>* BaseGenerator() const override {
- return base_;
- }
- // Advance should not be called on beyond-of-range iterators
- // so no component iterators must be beyond end of range, either.
- void Advance() override {
- assert(!AtEnd());
- // Advance the last iterator.
- ++std::get<sizeof...(T) - 1>(current_);
- // if that reaches end, propagate that up.
- AdvanceIfEnd<sizeof...(T) - 1>();
- ComputeCurrentValue();
- }
- ParamIteratorInterface<ParamType>* Clone() const override {
- return new IteratorImpl(*this);
- }
-
- const ParamType* Current() const override { return current_value_.get(); }
-
- bool Equals(const ParamIteratorInterface<ParamType>& other) const override {
- // Having the same base generator guarantees that the other
- // iterator is of the same type and we can downcast.
- GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
- << "The program attempted to compare iterators "
- << "from different generators." << std::endl;
- const IteratorImpl* typed_other =
- CheckedDowncastToActualType<const IteratorImpl>(&other);
-
- // We must report iterators equal if they both point beyond their
- // respective ranges. That can happen in a variety of fashions,
- // so we have to consult AtEnd().
- if (AtEnd() && typed_other->AtEnd()) return true;
-
- bool same = true;
- bool dummy[] = {
- (same = same && std::get<I>(current_) ==
- std::get<I>(typed_other->current_))...};
- (void)dummy;
- return same;
- }
-
- private:
- template <size_t ThisI>
- void AdvanceIfEnd() {
- if (std::get<ThisI>(current_) != std::get<ThisI>(end_)) return;
-
- bool last = ThisI == 0;
- if (last) {
- // We are done. Nothing else to propagate.
- return;
- }
-
- constexpr size_t NextI = ThisI - (ThisI != 0);
- std::get<ThisI>(current_) = std::get<ThisI>(begin_);
- ++std::get<NextI>(current_);
- AdvanceIfEnd<NextI>();
- }
-
- void ComputeCurrentValue() {
- if (!AtEnd())
- current_value_ = std::make_shared<ParamType>(*std::get<I>(current_)...);
- }
- bool AtEnd() const {
- bool at_end = false;
- bool dummy[] = {
- (at_end = at_end || std::get<I>(current_) == std::get<I>(end_))...};
- (void)dummy;
- return at_end;
- }
-
- const ParamGeneratorInterface<ParamType>* const base_;
- std::tuple<typename ParamGenerator<T>::iterator...> begin_;
- std::tuple<typename ParamGenerator<T>::iterator...> end_;
- std::tuple<typename ParamGenerator<T>::iterator...> current_;
- std::shared_ptr<ParamType> current_value_;
- };
-
- using Iterator = IteratorImpl<typename MakeIndexSequence<sizeof...(T)>::type>;
-
- std::tuple<ParamGenerator<T>...> generators_;
-};
-
-template <class... Gen>
-class CartesianProductHolder {
- public:
- CartesianProductHolder(const Gen&... g) : generators_(g...) {}
- template <typename... T>
- operator ParamGenerator<::std::tuple<T...>>() const {
- return ParamGenerator<::std::tuple<T...>>(
- new CartesianProductGenerator<T...>(generators_));
- }
-
- private:
- std::tuple<Gen...> generators_;
-};
-
-} // namespace internal
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+++ /dev/null
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file defines the GTEST_OS_* macro.
-// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
-
-// Determines the platform on which Google Test is compiled.
-#ifdef __CYGWIN__
-# define GTEST_OS_CYGWIN 1
-# elif defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__)
-# define GTEST_OS_WINDOWS_MINGW 1
-# define GTEST_OS_WINDOWS 1
-#elif defined _WIN32
-# define GTEST_OS_WINDOWS 1
-# ifdef _WIN32_WCE
-# define GTEST_OS_WINDOWS_MOBILE 1
-# elif defined(WINAPI_FAMILY)
-# include <winapifamily.h>
-# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-# define GTEST_OS_WINDOWS_DESKTOP 1
-# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
-# define GTEST_OS_WINDOWS_PHONE 1
-# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
-# define GTEST_OS_WINDOWS_RT 1
-# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
-# define GTEST_OS_WINDOWS_PHONE 1
-# define GTEST_OS_WINDOWS_TV_TITLE 1
-# else
- // WINAPI_FAMILY defined but no known partition matched.
- // Default to desktop.
-# define GTEST_OS_WINDOWS_DESKTOP 1
-# endif
-# else
-# define GTEST_OS_WINDOWS_DESKTOP 1
-# endif // _WIN32_WCE
-#elif defined __OS2__
-# define GTEST_OS_OS2 1
-#elif defined __APPLE__
-# define GTEST_OS_MAC 1
-# if TARGET_OS_IPHONE
-# define GTEST_OS_IOS 1
-# endif
-#elif defined __DragonFly__
-# define GTEST_OS_DRAGONFLY 1
-#elif defined __FreeBSD__
-# define GTEST_OS_FREEBSD 1
-#elif defined __Fuchsia__
-# define GTEST_OS_FUCHSIA 1
-#elif defined(__GLIBC__) && defined(__FreeBSD_kernel__)
-# define GTEST_OS_GNU_KFREEBSD 1
-#elif defined __linux__
-# define GTEST_OS_LINUX 1
-# if defined __ANDROID__
-# define GTEST_OS_LINUX_ANDROID 1
-# endif
-#elif defined __MVS__
-# define GTEST_OS_ZOS 1
-#elif defined(__sun) && defined(__SVR4)
-# define GTEST_OS_SOLARIS 1
-#elif defined(_AIX)
-# define GTEST_OS_AIX 1
-#elif defined(__hpux)
-# define GTEST_OS_HPUX 1
-#elif defined __native_client__
-# define GTEST_OS_NACL 1
-#elif defined __NetBSD__
-# define GTEST_OS_NETBSD 1
-#elif defined __OpenBSD__
-# define GTEST_OS_OPENBSD 1
-#elif defined __QNX__
-# define GTEST_OS_QNX 1
-#elif defined(__HAIKU__)
-#define GTEST_OS_HAIKU 1
-#endif // __CYGWIN__
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Low-level types and utilities for porting Google Test to various
-// platforms. All macros ending with _ and symbols defined in an
-// internal namespace are subject to change without notice. Code
-// outside Google Test MUST NOT USE THEM DIRECTLY. Macros that don't
-// end with _ are part of Google Test's public API and can be used by
-// code outside Google Test.
-//
-// This file is fundamental to Google Test. All other Google Test source
-// files are expected to #include this. Therefore, it cannot #include
-// any other Google Test header.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
-
-// Environment-describing macros
-// -----------------------------
-//
-// Google Test can be used in many different environments. Macros in
-// this section tell Google Test what kind of environment it is being
-// used in, such that Google Test can provide environment-specific
-// features and implementations.
-//
-// Google Test tries to automatically detect the properties of its
-// environment, so users usually don't need to worry about these
-// macros. However, the automatic detection is not perfect.
-// Sometimes it's necessary for a user to define some of the following
-// macros in the build script to override Google Test's decisions.
-//
-// If the user doesn't define a macro in the list, Google Test will
-// provide a default definition. After this header is #included, all
-// macros in this list will be defined to either 1 or 0.
-//
-// Notes to maintainers:
-// - Each macro here is a user-tweakable knob; do not grow the list
-// lightly.
-// - Use #if to key off these macros. Don't use #ifdef or "#if
-// defined(...)", which will not work as these macros are ALWAYS
-// defined.
-//
-// GTEST_HAS_CLONE - Define it to 1/0 to indicate that clone(2)
-// is/isn't available.
-// GTEST_HAS_EXCEPTIONS - Define it to 1/0 to indicate that exceptions
-// are enabled.
-// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
-// expressions are/aren't available.
-// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
-// is/isn't available.
-// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't
-// enabled.
-// GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that
-// std::wstring does/doesn't work (Google Test can
-// be used where std::wstring is unavailable).
-// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
-// compiler supports Microsoft's "Structured
-// Exception Handling".
-// GTEST_HAS_STREAM_REDIRECTION
-// - Define it to 1/0 to indicate whether the
-// platform supports I/O stream redirection using
-// dup() and dup2().
-// GTEST_LINKED_AS_SHARED_LIBRARY
-// - Define to 1 when compiling tests that use
-// Google Test as a shared library (known as
-// DLL on Windows).
-// GTEST_CREATE_SHARED_LIBRARY
-// - Define to 1 when compiling Google Test itself
-// as a shared library.
-// GTEST_DEFAULT_DEATH_TEST_STYLE
-// - The default value of --gtest_death_test_style.
-// The legacy default has been "fast" in the open
-// source version since 2008. The recommended value
-// is "threadsafe", and can be set in
-// custom/gtest-port.h.
-
-// Platform-indicating macros
-// --------------------------
-//
-// Macros indicating the platform on which Google Test is being used
-// (a macro is defined to 1 if compiled on the given platform;
-// otherwise UNDEFINED -- it's never defined to 0.). Google Test
-// defines these macros automatically. Code outside Google Test MUST
-// NOT define them.
-//
-// GTEST_OS_AIX - IBM AIX
-// GTEST_OS_CYGWIN - Cygwin
-// GTEST_OS_DRAGONFLY - DragonFlyBSD
-// GTEST_OS_FREEBSD - FreeBSD
-// GTEST_OS_FUCHSIA - Fuchsia
-// GTEST_OS_GNU_KFREEBSD - GNU/kFreeBSD
-// GTEST_OS_HAIKU - Haiku
-// GTEST_OS_HPUX - HP-UX
-// GTEST_OS_LINUX - Linux
-// GTEST_OS_LINUX_ANDROID - Google Android
-// GTEST_OS_MAC - Mac OS X
-// GTEST_OS_IOS - iOS
-// GTEST_OS_NACL - Google Native Client (NaCl)
-// GTEST_OS_NETBSD - NetBSD
-// GTEST_OS_OPENBSD - OpenBSD
-// GTEST_OS_OS2 - OS/2
-// GTEST_OS_QNX - QNX
-// GTEST_OS_SOLARIS - Sun Solaris
-// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
-// GTEST_OS_WINDOWS_DESKTOP - Windows Desktop
-// GTEST_OS_WINDOWS_MINGW - MinGW
-// GTEST_OS_WINDOWS_MOBILE - Windows Mobile
-// GTEST_OS_WINDOWS_PHONE - Windows Phone
-// GTEST_OS_WINDOWS_RT - Windows Store App/WinRT
-// GTEST_OS_ZOS - z/OS
-//
-// Among the platforms, Cygwin, Linux, Mac OS X, and Windows have the
-// most stable support. Since core members of the Google Test project
-// don't have access to other platforms, support for them may be less
-// stable. If you notice any problems on your platform, please notify
-// googletestframework@googlegroups.com (patches for fixing them are
-// even more welcome!).
-//
-// It is possible that none of the GTEST_OS_* macros are defined.
-
-// Feature-indicating macros
-// -------------------------
-//
-// Macros indicating which Google Test features are available (a macro
-// is defined to 1 if the corresponding feature is supported;
-// otherwise UNDEFINED -- it's never defined to 0.). Google Test
-// defines these macros automatically. Code outside Google Test MUST
-// NOT define them.
-//
-// These macros are public so that portable tests can be written.
-// Such tests typically surround code using a feature with an #if
-// which controls that code. For example:
-//
-// #if GTEST_HAS_DEATH_TEST
-// EXPECT_DEATH(DoSomethingDeadly());
-// #endif
-//
-// GTEST_HAS_DEATH_TEST - death tests
-// GTEST_HAS_TYPED_TEST - typed tests
-// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
-// GTEST_IS_THREADSAFE - Google Test is thread-safe.
-// GOOGLETEST_CM0007 DO NOT DELETE
-// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
-// GTEST_HAS_POSIX_RE (see above) which users can
-// define themselves.
-// GTEST_USES_SIMPLE_RE - our own simple regex is used;
-// the above RE\b(s) are mutually exclusive.
-
-// Misc public macros
-// ------------------
-//
-// GTEST_FLAG(flag_name) - references the variable corresponding to
-// the given Google Test flag.
-
-// Internal utilities
-// ------------------
-//
-// The following macros and utilities are for Google Test's INTERNAL
-// use only. Code outside Google Test MUST NOT USE THEM DIRECTLY.
-//
-// Macros for basic C++ coding:
-// GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
-// GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a
-// variable don't have to be used.
-// GTEST_DISALLOW_ASSIGN_ - disables operator=.
-// GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
-// GTEST_MUST_USE_RESULT_ - declares that a function's result must be used.
-// GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is
-// suppressed (constant conditional).
-// GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127
-// is suppressed.
-//
-// Synchronization:
-// Mutex, MutexLock, ThreadLocal, GetThreadCount()
-// - synchronization primitives.
-//
-// Regular expressions:
-// RE - a simple regular expression class using the POSIX
-// Extended Regular Expression syntax on UNIX-like platforms
-// GOOGLETEST_CM0008 DO NOT DELETE
-// or a reduced regular exception syntax on other
-// platforms, including Windows.
-// Logging:
-// GTEST_LOG_() - logs messages at the specified severity level.
-// LogToStderr() - directs all log messages to stderr.
-// FlushInfoLog() - flushes informational log messages.
-//
-// Stdout and stderr capturing:
-// CaptureStdout() - starts capturing stdout.
-// GetCapturedStdout() - stops capturing stdout and returns the captured
-// string.
-// CaptureStderr() - starts capturing stderr.
-// GetCapturedStderr() - stops capturing stderr and returns the captured
-// string.
-//
-// Integer types:
-// TypeWithSize - maps an integer to a int type.
-// Int32, UInt32, Int64, UInt64, TimeInMillis
-// - integers of known sizes.
-// BiggestInt - the biggest signed integer type.
-//
-// Command-line utilities:
-// GTEST_DECLARE_*() - declares a flag.
-// GTEST_DEFINE_*() - defines a flag.
-// GetInjectableArgvs() - returns the command line as a vector of strings.
-//
-// Environment variable utilities:
-// GetEnv() - gets the value of an environment variable.
-// BoolFromGTestEnv() - parses a bool environment variable.
-// Int32FromGTestEnv() - parses an Int32 environment variable.
-// StringFromGTestEnv() - parses a string environment variable.
-//
-// Deprecation warnings:
-// GTEST_INTERNAL_DEPRECATED(message) - attribute marking a function as
-// deprecated; calling a marked function
-// should generate a compiler warning
-
-#include <ctype.h> // for isspace, etc
-#include <stddef.h> // for ptrdiff_t
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <memory>
-#include <type_traits>
-
-#ifndef _WIN32_WCE
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif // !_WIN32_WCE
-
-#if defined __APPLE__
-# include <AvailabilityMacros.h>
-# include <TargetConditionals.h>
-#endif
-
-#include <algorithm> // NOLINT
-#include <iostream> // NOLINT
-#include <sstream> // NOLINT
-#include <string> // NOLINT
-#include <tuple>
-#include <utility>
-#include <vector> // NOLINT
-
-#include "gtest/internal/gtest-port-arch.h"
-#include "gtest/internal/custom/gtest-port.h"
-
-#if !defined(GTEST_DEV_EMAIL_)
-# define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
-# define GTEST_FLAG_PREFIX_ "gtest_"
-# define GTEST_FLAG_PREFIX_DASH_ "gtest-"
-# define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
-# define GTEST_NAME_ "Google Test"
-# define GTEST_PROJECT_URL_ "https://github.com/google/googletest/"
-#endif // !defined(GTEST_DEV_EMAIL_)
-
-#if !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
-# define GTEST_INIT_GOOGLE_TEST_NAME_ "testing::InitGoogleTest"
-#endif // !defined(GTEST_INIT_GOOGLE_TEST_NAME_)
-
-// Determines the version of gcc that is used to compile this.
-#ifdef __GNUC__
-// 40302 means version 4.3.2.
-# define GTEST_GCC_VER_ \
- (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
-#endif // __GNUC__
-
-// Macros for disabling Microsoft Visual C++ warnings.
-//
-// GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 4385)
-// /* code that triggers warnings C4800 and C4385 */
-// GTEST_DISABLE_MSC_WARNINGS_POP_()
-#if defined(_MSC_VER)
-# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings) \
- __pragma(warning(push)) \
- __pragma(warning(disable: warnings))
-# define GTEST_DISABLE_MSC_WARNINGS_POP_() \
- __pragma(warning(pop))
-#else
-// Not all compilers are MSVC
-# define GTEST_DISABLE_MSC_WARNINGS_PUSH_(warnings)
-# define GTEST_DISABLE_MSC_WARNINGS_POP_()
-#endif
-
-// Clang on Windows does not understand MSVC's pragma warning.
-// We need clang-specific way to disable function deprecation warning.
-#ifdef __clang__
-# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \
- _Pragma("clang diagnostic push") \
- _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") \
- _Pragma("clang diagnostic ignored \"-Wdeprecated-implementations\"")
-#define GTEST_DISABLE_MSC_DEPRECATED_POP_() \
- _Pragma("clang diagnostic pop")
-#else
-# define GTEST_DISABLE_MSC_DEPRECATED_PUSH_() \
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
-# define GTEST_DISABLE_MSC_DEPRECATED_POP_() \
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-#endif
-
-// Brings in definitions for functions used in the testing::internal::posix
-// namespace (read, write, close, chdir, isatty, stat). We do not currently
-// use them on Windows Mobile.
-#if GTEST_OS_WINDOWS
-# if !GTEST_OS_WINDOWS_MOBILE
-# include <direct.h>
-# include <io.h>
-# endif
-// In order to avoid having to include <windows.h>, use forward declaration
-#if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR)
-// MinGW defined _CRITICAL_SECTION and _RTL_CRITICAL_SECTION as two
-// separate (equivalent) structs, instead of using typedef
-typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION;
-#else
-// Assume CRITICAL_SECTION is a typedef of _RTL_CRITICAL_SECTION.
-// This assumption is verified by
-// WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION.
-typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
-#endif
-#else
-// This assumes that non-Windows OSes provide unistd.h. For OSes where this
-// is not the case, we need to include headers that provide the functions
-// mentioned above.
-# include <unistd.h>
-# include <strings.h>
-#endif // GTEST_OS_WINDOWS
-
-#if GTEST_OS_LINUX_ANDROID
-// Used to define __ANDROID_API__ matching the target NDK API level.
-# include <android/api-level.h> // NOLINT
-#endif
-
-// Defines this to true if and only if Google Test can use POSIX regular
-// expressions.
-#ifndef GTEST_HAS_POSIX_RE
-# if GTEST_OS_LINUX_ANDROID
-// On Android, <regex.h> is only available starting with Gingerbread.
-# define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
-# else
-# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
-# endif
-#endif
-
-#if GTEST_USES_PCRE
-// The appropriate headers have already been included.
-
-#elif GTEST_HAS_POSIX_RE
-
-// On some platforms, <regex.h> needs someone to define size_t, and
-// won't compile otherwise. We can #include it here as we already
-// included <stdlib.h>, which is guaranteed to define size_t through
-// <stddef.h>.
-# include <regex.h> // NOLINT
-
-# define GTEST_USES_POSIX_RE 1
-
-#elif GTEST_OS_WINDOWS
-
-// <regex.h> is not available on Windows. Use our own simple regex
-// implementation instead.
-# define GTEST_USES_SIMPLE_RE 1
-
-#else
-
-// <regex.h> may not be available on this platform. Use our own
-// simple regex implementation instead.
-# define GTEST_USES_SIMPLE_RE 1
-
-#endif // GTEST_USES_PCRE
-
-#ifndef GTEST_HAS_EXCEPTIONS
-// The user didn't tell us whether exceptions are enabled, so we need
-// to figure it out.
-# if defined(_MSC_VER) && defined(_CPPUNWIND)
-// MSVC defines _CPPUNWIND to 1 if and only if exceptions are enabled.
-# define GTEST_HAS_EXCEPTIONS 1
-# elif defined(__BORLANDC__)
-// C++Builder's implementation of the STL uses the _HAS_EXCEPTIONS
-// macro to enable exceptions, so we'll do the same.
-// Assumes that exceptions are enabled by default.
-# ifndef _HAS_EXCEPTIONS
-# define _HAS_EXCEPTIONS 1
-# endif // _HAS_EXCEPTIONS
-# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
-# elif defined(__clang__)
-// clang defines __EXCEPTIONS if and only if exceptions are enabled before clang
-// 220714, but if and only if cleanups are enabled after that. In Obj-C++ files,
-// there can be cleanups for ObjC exceptions which also need cleanups, even if
-// C++ exceptions are disabled. clang has __has_feature(cxx_exceptions) which
-// checks for C++ exceptions starting at clang r206352, but which checked for
-// cleanups prior to that. To reliably check for C++ exception availability with
-// clang, check for
-// __EXCEPTIONS && __has_feature(cxx_exceptions).
-# define GTEST_HAS_EXCEPTIONS (__EXCEPTIONS && __has_feature(cxx_exceptions))
-# elif defined(__GNUC__) && __EXCEPTIONS
-// gcc defines __EXCEPTIONS to 1 if and only if exceptions are enabled.
-# define GTEST_HAS_EXCEPTIONS 1
-# elif defined(__SUNPRO_CC)
-// Sun Pro CC supports exceptions. However, there is no compile-time way of
-// detecting whether they are enabled or not. Therefore, we assume that
-// they are enabled unless the user tells us otherwise.
-# define GTEST_HAS_EXCEPTIONS 1
-# elif defined(__IBMCPP__) && __EXCEPTIONS
-// xlC defines __EXCEPTIONS to 1 if and only if exceptions are enabled.
-# define GTEST_HAS_EXCEPTIONS 1
-# elif defined(__HP_aCC)
-// Exception handling is in effect by default in HP aCC compiler. It has to
-// be turned of by +noeh compiler option if desired.
-# define GTEST_HAS_EXCEPTIONS 1
-# else
-// For other compilers, we assume exceptions are disabled to be
-// conservative.
-# define GTEST_HAS_EXCEPTIONS 0
-# endif // defined(_MSC_VER) || defined(__BORLANDC__)
-#endif // GTEST_HAS_EXCEPTIONS
-
-#if !defined(GTEST_HAS_STD_STRING)
-// Even though we don't use this macro any longer, we keep it in case
-// some clients still depend on it.
-# define GTEST_HAS_STD_STRING 1
-#elif !GTEST_HAS_STD_STRING
-// The user told us that ::std::string isn't available.
-# error "::std::string isn't available."
-#endif // !defined(GTEST_HAS_STD_STRING)
-
-#ifndef GTEST_HAS_STD_WSTRING
-// The user didn't tell us whether ::std::wstring is available, so we need
-// to figure it out.
-// Cygwin 1.7 and below doesn't support ::std::wstring.
-// Solaris' libc++ doesn't support it either. Android has
-// no support for it at least as recent as Froyo (2.2).
-#define GTEST_HAS_STD_WSTRING \
- (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
- GTEST_OS_HAIKU))
-
-#endif // GTEST_HAS_STD_WSTRING
-
-// Determines whether RTTI is available.
-#ifndef GTEST_HAS_RTTI
-// The user didn't tell us whether RTTI is enabled, so we need to
-// figure it out.
-
-# ifdef _MSC_VER
-
-#ifdef _CPPRTTI // MSVC defines this macro if and only if RTTI is enabled.
-# define GTEST_HAS_RTTI 1
-# else
-# define GTEST_HAS_RTTI 0
-# endif
-
-// Starting with version 4.3.2, gcc defines __GXX_RTTI if and only if RTTI is
-// enabled.
-# elif defined(__GNUC__)
-
-# ifdef __GXX_RTTI
-// When building against STLport with the Android NDK and with
-// -frtti -fno-exceptions, the build fails at link time with undefined
-// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
-// so disable RTTI when detected.
-# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \
- !defined(__EXCEPTIONS)
-# define GTEST_HAS_RTTI 0
-# else
-# define GTEST_HAS_RTTI 1
-# endif // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
-# else
-# define GTEST_HAS_RTTI 0
-# endif // __GXX_RTTI
-
-// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
-// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
-// first version with C++ support.
-# elif defined(__clang__)
-
-# define GTEST_HAS_RTTI __has_feature(cxx_rtti)
-
-// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
-// both the typeid and dynamic_cast features are present.
-# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
-
-# ifdef __RTTI_ALL__
-# define GTEST_HAS_RTTI 1
-# else
-# define GTEST_HAS_RTTI 0
-# endif
-
-# else
-
-// For all other compilers, we assume RTTI is enabled.
-# define GTEST_HAS_RTTI 1
-
-# endif // _MSC_VER
-
-#endif // GTEST_HAS_RTTI
-
-// It's this header's responsibility to #include <typeinfo> when RTTI
-// is enabled.
-#if GTEST_HAS_RTTI
-# include <typeinfo>
-#endif
-
-// Determines whether Google Test can use the pthreads library.
-#ifndef GTEST_HAS_PTHREAD
-// The user didn't tell us explicitly, so we make reasonable assumptions about
-// which platforms have pthreads support.
-//
-// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
-// to your compiler flags.
-#define GTEST_HAS_PTHREAD \
- (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX || GTEST_OS_QNX || \
- GTEST_OS_FREEBSD || GTEST_OS_NACL || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \
- GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_OPENBSD || \
- GTEST_OS_HAIKU)
-#endif // GTEST_HAS_PTHREAD
-
-#if GTEST_HAS_PTHREAD
-// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
-// true.
-# include <pthread.h> // NOLINT
-
-// For timespec and nanosleep, used below.
-# include <time.h> // NOLINT
-#endif
-
-// Determines whether clone(2) is supported.
-// Usually it will only be available on Linux, excluding
-// Linux on the Itanium architecture.
-// Also see http://linux.die.net/man/2/clone.
-#ifndef GTEST_HAS_CLONE
-// The user didn't tell us, so we need to figure it out.
-
-# if GTEST_OS_LINUX && !defined(__ia64__)
-# if GTEST_OS_LINUX_ANDROID
-// On Android, clone() became available at different API levels for each 32-bit
-// architecture.
-# if defined(__LP64__) || \
- (defined(__arm__) && __ANDROID_API__ >= 9) || \
- (defined(__mips__) && __ANDROID_API__ >= 12) || \
- (defined(__i386__) && __ANDROID_API__ >= 17)
-# define GTEST_HAS_CLONE 1
-# else
-# define GTEST_HAS_CLONE 0
-# endif
-# else
-# define GTEST_HAS_CLONE 1
-# endif
-# else
-# define GTEST_HAS_CLONE 0
-# endif // GTEST_OS_LINUX && !defined(__ia64__)
-
-#endif // GTEST_HAS_CLONE
-
-// Determines whether to support stream redirection. This is used to test
-// output correctness and to implement death tests.
-#ifndef GTEST_HAS_STREAM_REDIRECTION
-// By default, we assume that stream redirection is supported on all
-// platforms except known mobile ones.
-# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
-# define GTEST_HAS_STREAM_REDIRECTION 0
-# else
-# define GTEST_HAS_STREAM_REDIRECTION 1
-# endif // !GTEST_OS_WINDOWS_MOBILE
-#endif // GTEST_HAS_STREAM_REDIRECTION
-
-// Determines whether to support death tests.
-// pops up a dialog window that cannot be suppressed programmatically.
-#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
- (GTEST_OS_MAC && !GTEST_OS_IOS) || \
- (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER) || GTEST_OS_WINDOWS_MINGW || \
- GTEST_OS_AIX || GTEST_OS_HPUX || GTEST_OS_OPENBSD || GTEST_OS_QNX || \
- GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_FUCHSIA || \
- GTEST_OS_DRAGONFLY || GTEST_OS_GNU_KFREEBSD || GTEST_OS_HAIKU)
-# define GTEST_HAS_DEATH_TEST 1
-#endif
-
-// Determines whether to support type-driven tests.
-
-// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
-// Sun Pro CC, IBM Visual Age, and HP aCC support.
-#if defined(__GNUC__) || defined(_MSC_VER) || defined(__SUNPRO_CC) || \
- defined(__IBMCPP__) || defined(__HP_aCC)
-# define GTEST_HAS_TYPED_TEST 1
-# define GTEST_HAS_TYPED_TEST_P 1
-#endif
-
-// Determines whether the system compiler uses UTF-16 for encoding wide strings.
-#define GTEST_WIDE_STRING_USES_UTF16_ \
- (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_AIX || GTEST_OS_OS2)
-
-// Determines whether test results can be streamed to a socket.
-#if GTEST_OS_LINUX || GTEST_OS_GNU_KFREEBSD || GTEST_OS_DRAGONFLY || \
- GTEST_OS_FREEBSD || GTEST_OS_NETBSD || GTEST_OS_OPENBSD
-# define GTEST_CAN_STREAM_RESULTS_ 1
-#endif
-
-// Defines some utility macros.
-
-// The GNU compiler emits a warning if nested "if" statements are followed by
-// an "else" statement and braces are not used to explicitly disambiguate the
-// "else" binding. This leads to problems with code like:
-//
-// if (gate)
-// ASSERT_*(condition) << "Some message";
-//
-// The "switch (0) case 0:" idiom is used to suppress this.
-#ifdef __INTEL_COMPILER
-# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
-#else
-# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT
-#endif
-
-// Use this annotation at the end of a struct/class definition to
-// prevent the compiler from optimizing away instances that are never
-// used. This is useful when all interesting logic happens inside the
-// c'tor and / or d'tor. Example:
-//
-// struct Foo {
-// Foo() { ... }
-// } GTEST_ATTRIBUTE_UNUSED_;
-//
-// Also use it after a variable or parameter declaration to tell the
-// compiler the variable/parameter does not have to be used.
-#if defined(__GNUC__) && !defined(COMPILER_ICC)
-# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
-#elif defined(__clang__)
-# if __has_attribute(unused)
-# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
-# endif
-#endif
-#ifndef GTEST_ATTRIBUTE_UNUSED_
-# define GTEST_ATTRIBUTE_UNUSED_
-#endif
-
-// Use this annotation before a function that takes a printf format string.
-#if (defined(__GNUC__) || defined(__clang__)) && !defined(COMPILER_ICC)
-# if defined(__MINGW_PRINTF_FORMAT)
-// MinGW has two different printf implementations. Ensure the format macro
-// matches the selected implementation. See
-// https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/.
-# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
- __attribute__((__format__(__MINGW_PRINTF_FORMAT, string_index, \
- first_to_check)))
-# else
-# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check) \
- __attribute__((__format__(__printf__, string_index, first_to_check)))
-# endif
-#else
-# define GTEST_ATTRIBUTE_PRINTF_(string_index, first_to_check)
-#endif
-
-
-// A macro to disallow operator=
-// This should be used in the private: declarations for a class.
-#define GTEST_DISALLOW_ASSIGN_(type) \
- void operator=(type const &) = delete
-
-// A macro to disallow copy constructor and operator=
-// This should be used in the private: declarations for a class.
-#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \
- type(type const &) = delete; \
- GTEST_DISALLOW_ASSIGN_(type)
-
-// Tell the compiler to warn about unused return values for functions declared
-// with this macro. The macro should be used on function declarations
-// following the argument list:
-//
-// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
-#if defined(__GNUC__) && !defined(COMPILER_ICC)
-# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
-#else
-# define GTEST_MUST_USE_RESULT_
-#endif // __GNUC__ && !COMPILER_ICC
-
-// MS C++ compiler emits warning when a conditional expression is compile time
-// constant. In some contexts this warning is false positive and needs to be
-// suppressed. Use the following two macros in such cases:
-//
-// GTEST_INTENTIONAL_CONST_COND_PUSH_()
-// while (true) {
-// GTEST_INTENTIONAL_CONST_COND_POP_()
-// }
-# define GTEST_INTENTIONAL_CONST_COND_PUSH_() \
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127)
-# define GTEST_INTENTIONAL_CONST_COND_POP_() \
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-
-// Determine whether the compiler supports Microsoft's Structured Exception
-// Handling. This is supported by several Windows compilers but generally
-// does not exist on any other system.
-#ifndef GTEST_HAS_SEH
-// The user didn't tell us, so we need to figure it out.
-
-# if defined(_MSC_VER) || defined(__BORLANDC__)
-// These two compilers are known to support SEH.
-# define GTEST_HAS_SEH 1
-# else
-// Assume no SEH.
-# define GTEST_HAS_SEH 0
-# endif
-
-#endif // GTEST_HAS_SEH
-
-#ifndef GTEST_IS_THREADSAFE
-
-#define GTEST_IS_THREADSAFE \
- (GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ || \
- (GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT) || \
- GTEST_HAS_PTHREAD)
-
-#endif // GTEST_IS_THREADSAFE
-
-// GTEST_API_ qualifies all symbols that must be exported. The definitions below
-// are guarded by #ifndef to give embedders a chance to define GTEST_API_ in
-// gtest/internal/custom/gtest-port.h
-#ifndef GTEST_API_
-
-#ifdef _MSC_VER
-# if GTEST_LINKED_AS_SHARED_LIBRARY
-# define GTEST_API_ __declspec(dllimport)
-# elif GTEST_CREATE_SHARED_LIBRARY
-# define GTEST_API_ __declspec(dllexport)
-# endif
-#elif __GNUC__ >= 4 || defined(__clang__)
-# define GTEST_API_ __attribute__((visibility ("default")))
-#endif // _MSC_VER
-
-#endif // GTEST_API_
-
-#ifndef GTEST_API_
-# define GTEST_API_
-#endif // GTEST_API_
-
-#ifndef GTEST_DEFAULT_DEATH_TEST_STYLE
-# define GTEST_DEFAULT_DEATH_TEST_STYLE "fast"
-#endif // GTEST_DEFAULT_DEATH_TEST_STYLE
-
-#ifdef __GNUC__
-// Ask the compiler to never inline a given function.
-# define GTEST_NO_INLINE_ __attribute__((noinline))
-#else
-# define GTEST_NO_INLINE_
-#endif
-
-// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
-#if !defined(GTEST_HAS_CXXABI_H_)
-# if defined(__GLIBCXX__) || (defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
-# define GTEST_HAS_CXXABI_H_ 1
-# else
-# define GTEST_HAS_CXXABI_H_ 0
-# endif
-#endif
-
-// A function level attribute to disable checking for use of uninitialized
-// memory when built with MemorySanitizer.
-#if defined(__clang__)
-# if __has_feature(memory_sanitizer)
-# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ \
- __attribute__((no_sanitize_memory))
-# else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
-# endif // __has_feature(memory_sanitizer)
-#else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
-#endif // __clang__
-
-// A function level attribute to disable AddressSanitizer instrumentation.
-#if defined(__clang__)
-# if __has_feature(address_sanitizer)
-# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ \
- __attribute__((no_sanitize_address))
-# else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
-# endif // __has_feature(address_sanitizer)
-#else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
-#endif // __clang__
-
-// A function level attribute to disable HWAddressSanitizer instrumentation.
-#if defined(__clang__)
-# if __has_feature(hwaddress_sanitizer)
-# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_ \
- __attribute__((no_sanitize("hwaddress")))
-# else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-# endif // __has_feature(hwaddress_sanitizer)
-#else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-#endif // __clang__
-
-// A function level attribute to disable ThreadSanitizer instrumentation.
-#if defined(__clang__)
-# if __has_feature(thread_sanitizer)
-# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_ \
- __attribute__((no_sanitize_thread))
-# else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
-# endif // __has_feature(thread_sanitizer)
-#else
-# define GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
-#endif // __clang__
-
-namespace testing {
-
-class Message;
-
-// Legacy imports for backwards compatibility.
-// New code should use std:: names directly.
-using std::get;
-using std::make_tuple;
-using std::tuple;
-using std::tuple_element;
-using std::tuple_size;
-
-namespace internal {
-
-// A secret type that Google Test users don't know about. It has no
-// definition on purpose. Therefore it's impossible to create a
-// Secret object, which is what we want.
-class Secret;
-
-// The GTEST_COMPILE_ASSERT_ is a legacy macro used to verify that a compile
-// time expression is true (in new code, use static_assert instead). For
-// example, you could use it to verify the size of a static array:
-//
-// GTEST_COMPILE_ASSERT_(GTEST_ARRAY_SIZE_(names) == NUM_NAMES,
-// names_incorrect_size);
-//
-// The second argument to the macro must be a valid C++ identifier. If the
-// expression is false, compiler will issue an error containing this identifier.
-#define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg)
-
-// Evaluates to the number of elements in 'array'.
-#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0]))
-
-// A helper for suppressing warnings on constant condition. It just
-// returns 'condition'.
-GTEST_API_ bool IsTrue(bool condition);
-
-// Defines RE.
-
-#if GTEST_USES_PCRE
-// if used, PCRE is injected by custom/gtest-port.h
-#elif GTEST_USES_POSIX_RE || GTEST_USES_SIMPLE_RE
-
-// A simple C++ wrapper for <regex.h>. It uses the POSIX Extended
-// Regular Expression syntax.
-class GTEST_API_ RE {
- public:
- // A copy constructor is required by the Standard to initialize object
- // references from r-values.
- RE(const RE& other) { Init(other.pattern()); }
-
- // Constructs an RE from a string.
- RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT
-
- RE(const char* regex) { Init(regex); } // NOLINT
- ~RE();
-
- // Returns the string representation of the regex.
- const char* pattern() const { return pattern_; }
-
- // FullMatch(str, re) returns true if and only if regular expression re
- // matches the entire str.
- // PartialMatch(str, re) returns true if and only if regular expression re
- // matches a substring of str (including str itself).
- static bool FullMatch(const ::std::string& str, const RE& re) {
- return FullMatch(str.c_str(), re);
- }
- static bool PartialMatch(const ::std::string& str, const RE& re) {
- return PartialMatch(str.c_str(), re);
- }
-
- static bool FullMatch(const char* str, const RE& re);
- static bool PartialMatch(const char* str, const RE& re);
-
- private:
- void Init(const char* regex);
- const char* pattern_;
- bool is_valid_;
-
-# if GTEST_USES_POSIX_RE
-
- regex_t full_regex_; // For FullMatch().
- regex_t partial_regex_; // For PartialMatch().
-
-# else // GTEST_USES_SIMPLE_RE
-
- const char* full_pattern_; // For FullMatch();
-
-# endif
-
- GTEST_DISALLOW_ASSIGN_(RE);
-};
-
-#endif // GTEST_USES_PCRE
-
-// Formats a source file path and a line number as they would appear
-// in an error message from the compiler used to compile this code.
-GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
-
-// Formats a file location for compiler-independent XML output.
-// Although this function is not platform dependent, we put it next to
-// FormatFileLocation in order to contrast the two functions.
-GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
- int line);
-
-// Defines logging utilities:
-// GTEST_LOG_(severity) - logs messages at the specified severity level. The
-// message itself is streamed into the macro.
-// LogToStderr() - directs all log messages to stderr.
-// FlushInfoLog() - flushes informational log messages.
-
-enum GTestLogSeverity {
- GTEST_INFO,
- GTEST_WARNING,
- GTEST_ERROR,
- GTEST_FATAL
-};
-
-// Formats log entry severity, provides a stream object for streaming the
-// log message, and terminates the message with a newline when going out of
-// scope.
-class GTEST_API_ GTestLog {
- public:
- GTestLog(GTestLogSeverity severity, const char* file, int line);
-
- // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
- ~GTestLog();
-
- ::std::ostream& GetStream() { return ::std::cerr; }
-
- private:
- const GTestLogSeverity severity_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
-};
-
-#if !defined(GTEST_LOG_)
-
-# define GTEST_LOG_(severity) \
- ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
- __FILE__, __LINE__).GetStream()
-
-inline void LogToStderr() {}
-inline void FlushInfoLog() { fflush(nullptr); }
-
-#endif // !defined(GTEST_LOG_)
-
-#if !defined(GTEST_CHECK_)
-// INTERNAL IMPLEMENTATION - DO NOT USE.
-//
-// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
-// is not satisfied.
-// Synopsys:
-// GTEST_CHECK_(boolean_condition);
-// or
-// GTEST_CHECK_(boolean_condition) << "Additional message";
-//
-// This checks the condition and if the condition is not satisfied
-// it prints message about the condition violation, including the
-// condition itself, plus additional message streamed into it, if any,
-// and then it aborts the program. It aborts the program irrespective of
-// whether it is built in the debug mode or not.
-# define GTEST_CHECK_(condition) \
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (::testing::internal::IsTrue(condition)) \
- ; \
- else \
- GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
-#endif // !defined(GTEST_CHECK_)
-
-// An all-mode assert to verify that the given POSIX-style function
-// call returns 0 (indicating success). Known limitation: this
-// doesn't expand to a balanced 'if' statement, so enclose the macro
-// in {} if you need to use it as the only statement in an 'if'
-// branch.
-#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
- if (const int gtest_error = (posix_call)) \
- GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
- << gtest_error
-
-// Transforms "T" into "const T&" according to standard reference collapsing
-// rules (this is only needed as a backport for C++98 compilers that do not
-// support reference collapsing). Specifically, it transforms:
-//
-// char ==> const char&
-// const char ==> const char&
-// char& ==> char&
-// const char& ==> const char&
-//
-// Note that the non-const reference will not have "const" added. This is
-// standard, and necessary so that "T" can always bind to "const T&".
-template <typename T>
-struct ConstRef { typedef const T& type; };
-template <typename T>
-struct ConstRef<T&> { typedef T& type; };
-
-// The argument T must depend on some template parameters.
-#define GTEST_REFERENCE_TO_CONST_(T) \
- typename ::testing::internal::ConstRef<T>::type
-
-// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
-//
-// Use ImplicitCast_ as a safe version of static_cast for upcasting in
-// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
-// const Foo*). When you use ImplicitCast_, the compiler checks that
-// the cast is safe. Such explicit ImplicitCast_s are necessary in
-// surprisingly many situations where C++ demands an exact type match
-// instead of an argument type convertable to a target type.
-//
-// The syntax for using ImplicitCast_ is the same as for static_cast:
-//
-// ImplicitCast_<ToType>(expr)
-//
-// ImplicitCast_ would have been part of the C++ standard library,
-// but the proposal was submitted too late. It will probably make
-// its way into the language in the future.
-//
-// This relatively ugly name is intentional. It prevents clashes with
-// similar functions users may have (e.g., implicit_cast). The internal
-// namespace alone is not enough because the function can be found by ADL.
-template<typename To>
-inline To ImplicitCast_(To x) { return x; }
-
-// When you upcast (that is, cast a pointer from type Foo to type
-// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
-// always succeed. When you downcast (that is, cast a pointer from
-// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
-// how do you know the pointer is really of type SubclassOfFoo? It
-// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
-// when you downcast, you should use this macro. In debug mode, we
-// use dynamic_cast<> to double-check the downcast is legal (we die
-// if it's not). In normal mode, we do the efficient static_cast<>
-// instead. Thus, it's important to test in debug mode to make sure
-// the cast is legal!
-// This is the only place in the code we should use dynamic_cast<>.
-// In particular, you SHOULDN'T be using dynamic_cast<> in order to
-// do RTTI (eg code like this:
-// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
-// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
-// You should design the code some other way not to need this.
-//
-// This relatively ugly name is intentional. It prevents clashes with
-// similar functions users may have (e.g., down_cast). The internal
-// namespace alone is not enough because the function can be found by ADL.
-template<typename To, typename From> // use like this: DownCast_<T*>(foo);
-inline To DownCast_(From* f) { // so we only accept pointers
- // Ensures that To is a sub-type of From *. This test is here only
- // for compile-time type checking, and has no overhead in an
- // optimized build at run-time, as it will be optimized away
- // completely.
- GTEST_INTENTIONAL_CONST_COND_PUSH_()
- if (false) {
- GTEST_INTENTIONAL_CONST_COND_POP_()
- const To to = nullptr;
- ::testing::internal::ImplicitCast_<From*>(to);
- }
-
-#if GTEST_HAS_RTTI
- // RTTI: debug mode only!
- GTEST_CHECK_(f == nullptr || dynamic_cast<To>(f) != nullptr);
-#endif
- return static_cast<To>(f);
-}
-
-// Downcasts the pointer of type Base to Derived.
-// Derived must be a subclass of Base. The parameter MUST
-// point to a class of type Derived, not any subclass of it.
-// When RTTI is available, the function performs a runtime
-// check to enforce this.
-template <class Derived, class Base>
-Derived* CheckedDowncastToActualType(Base* base) {
-#if GTEST_HAS_RTTI
- GTEST_CHECK_(typeid(*base) == typeid(Derived));
-#endif
-
-#if GTEST_HAS_DOWNCAST_
- return ::down_cast<Derived*>(base);
-#elif GTEST_HAS_RTTI
- return dynamic_cast<Derived*>(base); // NOLINT
-#else
- return static_cast<Derived*>(base); // Poor man's downcast.
-#endif
-}
-
-#if GTEST_HAS_STREAM_REDIRECTION
-
-// Defines the stderr capturer:
-// CaptureStdout - starts capturing stdout.
-// GetCapturedStdout - stops capturing stdout and returns the captured string.
-// CaptureStderr - starts capturing stderr.
-// GetCapturedStderr - stops capturing stderr and returns the captured string.
-//
-GTEST_API_ void CaptureStdout();
-GTEST_API_ std::string GetCapturedStdout();
-GTEST_API_ void CaptureStderr();
-GTEST_API_ std::string GetCapturedStderr();
-
-#endif // GTEST_HAS_STREAM_REDIRECTION
-// Returns the size (in bytes) of a file.
-GTEST_API_ size_t GetFileSize(FILE* file);
-
-// Reads the entire content of a file as a string.
-GTEST_API_ std::string ReadEntireFile(FILE* file);
-
-// All command line arguments.
-GTEST_API_ std::vector<std::string> GetArgvs();
-
-#if GTEST_HAS_DEATH_TEST
-
-std::vector<std::string> GetInjectableArgvs();
-// Deprecated: pass the args vector by value instead.
-void SetInjectableArgvs(const std::vector<std::string>* new_argvs);
-void SetInjectableArgvs(const std::vector<std::string>& new_argvs);
-void ClearInjectableArgvs();
-
-#endif // GTEST_HAS_DEATH_TEST
-
-// Defines synchronization primitives.
-#if GTEST_IS_THREADSAFE
-# if GTEST_HAS_PTHREAD
-// Sleeps for (roughly) n milliseconds. This function is only for testing
-// Google Test's own constructs. Don't use it in user tests, either
-// directly or indirectly.
-inline void SleepMilliseconds(int n) {
- const timespec time = {
- 0, // 0 seconds.
- n * 1000L * 1000L, // And n ms.
- };
- nanosleep(&time, nullptr);
-}
-# endif // GTEST_HAS_PTHREAD
-
-# if GTEST_HAS_NOTIFICATION_
-// Notification has already been imported into the namespace.
-// Nothing to do here.
-
-# elif GTEST_HAS_PTHREAD
-// Allows a controller thread to pause execution of newly created
-// threads until notified. Instances of this class must be created
-// and destroyed in the controller thread.
-//
-// This class is only for testing Google Test's own constructs. Do not
-// use it in user tests, either directly or indirectly.
-class Notification {
- public:
- Notification() : notified_(false) {
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
- }
- ~Notification() {
- pthread_mutex_destroy(&mutex_);
- }
-
- // Notifies all threads created with this notification to start. Must
- // be called from the controller thread.
- void Notify() {
- pthread_mutex_lock(&mutex_);
- notified_ = true;
- pthread_mutex_unlock(&mutex_);
- }
-
- // Blocks until the controller thread notifies. Must be called from a test
- // thread.
- void WaitForNotification() {
- for (;;) {
- pthread_mutex_lock(&mutex_);
- const bool notified = notified_;
- pthread_mutex_unlock(&mutex_);
- if (notified)
- break;
- SleepMilliseconds(10);
- }
- }
-
- private:
- pthread_mutex_t mutex_;
- bool notified_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
-};
-
-# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
-
-GTEST_API_ void SleepMilliseconds(int n);
-
-// Provides leak-safe Windows kernel handle ownership.
-// Used in death tests and in threading support.
-class GTEST_API_ AutoHandle {
- public:
- // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to
- // avoid including <windows.h> in this header file. Including <windows.h> is
- // undesirable because it defines a lot of symbols and macros that tend to
- // conflict with client code. This assumption is verified by
- // WindowsTypesTest.HANDLEIsVoidStar.
- typedef void* Handle;
- AutoHandle();
- explicit AutoHandle(Handle handle);
-
- ~AutoHandle();
-
- Handle Get() const;
- void Reset();
- void Reset(Handle handle);
-
- private:
- // Returns true if and only if the handle is a valid handle object that can be
- // closed.
- bool IsCloseable() const;
-
- Handle handle_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
-};
-
-// Allows a controller thread to pause execution of newly created
-// threads until notified. Instances of this class must be created
-// and destroyed in the controller thread.
-//
-// This class is only for testing Google Test's own constructs. Do not
-// use it in user tests, either directly or indirectly.
-class GTEST_API_ Notification {
- public:
- Notification();
- void Notify();
- void WaitForNotification();
-
- private:
- AutoHandle event_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
-};
-# endif // GTEST_HAS_NOTIFICATION_
-
-// On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD
-// defined, but we don't want to use MinGW's pthreads implementation, which
-// has conformance problems with some versions of the POSIX standard.
-# if GTEST_HAS_PTHREAD && !GTEST_OS_WINDOWS_MINGW
-
-// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
-// Consequently, it cannot select a correct instantiation of ThreadWithParam
-// in order to call its Run(). Introducing ThreadWithParamBase as a
-// non-templated base class for ThreadWithParam allows us to bypass this
-// problem.
-class ThreadWithParamBase {
- public:
- virtual ~ThreadWithParamBase() {}
- virtual void Run() = 0;
-};
-
-// pthread_create() accepts a pointer to a function type with the C linkage.
-// According to the Standard (7.5/1), function types with different linkages
-// are different even if they are otherwise identical. Some compilers (for
-// example, SunStudio) treat them as different types. Since class methods
-// cannot be defined with C-linkage we need to define a free C-function to
-// pass into pthread_create().
-extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
- static_cast<ThreadWithParamBase*>(thread)->Run();
- return nullptr;
-}
-
-// Helper class for testing Google Test's multi-threading constructs.
-// To use it, write:
-//
-// void ThreadFunc(int param) { /* Do things with param */ }
-// Notification thread_can_start;
-// ...
-// // The thread_can_start parameter is optional; you can supply NULL.
-// ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
-// thread_can_start.Notify();
-//
-// These classes are only for testing Google Test's own constructs. Do
-// not use them in user tests, either directly or indirectly.
-template <typename T>
-class ThreadWithParam : public ThreadWithParamBase {
- public:
- typedef void UserThreadFunc(T);
-
- ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
- : func_(func),
- param_(param),
- thread_can_start_(thread_can_start),
- finished_(false) {
- ThreadWithParamBase* const base = this;
- // The thread can be created only after all fields except thread_
- // have been initialized.
- GTEST_CHECK_POSIX_SUCCESS_(
- pthread_create(&thread_, nullptr, &ThreadFuncWithCLinkage, base));
- }
- ~ThreadWithParam() override { Join(); }
-
- void Join() {
- if (!finished_) {
- GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, nullptr));
- finished_ = true;
- }
- }
-
- void Run() override {
- if (thread_can_start_ != nullptr) thread_can_start_->WaitForNotification();
- func_(param_);
- }
-
- private:
- UserThreadFunc* const func_; // User-supplied thread function.
- const T param_; // User-supplied parameter to the thread function.
- // When non-NULL, used to block execution until the controller thread
- // notifies.
- Notification* const thread_can_start_;
- bool finished_; // true if and only if we know that the thread function has
- // finished.
- pthread_t thread_; // The native thread object.
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
-};
-# endif // !GTEST_OS_WINDOWS && GTEST_HAS_PTHREAD ||
- // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
-
-# if GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
-// Mutex and ThreadLocal have already been imported into the namespace.
-// Nothing to do here.
-
-# elif GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
-
-// Mutex implements mutex on Windows platforms. It is used in conjunction
-// with class MutexLock:
-//
-// Mutex mutex;
-// ...
-// MutexLock lock(&mutex); // Acquires the mutex and releases it at the
-// // end of the current scope.
-//
-// A static Mutex *must* be defined or declared using one of the following
-// macros:
-// GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
-// GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
-//
-// (A non-static Mutex is defined/declared in the usual way).
-class GTEST_API_ Mutex {
- public:
- enum MutexType { kStatic = 0, kDynamic = 1 };
- // We rely on kStaticMutex being 0 as it is to what the linker initializes
- // type_ in static mutexes. critical_section_ will be initialized lazily
- // in ThreadSafeLazyInit().
- enum StaticConstructorSelector { kStaticMutex = 0 };
-
- // This constructor intentionally does nothing. It relies on type_ being
- // statically initialized to 0 (effectively setting it to kStatic) and on
- // ThreadSafeLazyInit() to lazily initialize the rest of the members.
- explicit Mutex(StaticConstructorSelector /*dummy*/) {}
-
- Mutex();
- ~Mutex();
-
- void Lock();
-
- void Unlock();
-
- // Does nothing if the current thread holds the mutex. Otherwise, crashes
- // with high probability.
- void AssertHeld();
-
- private:
- // Initializes owner_thread_id_ and critical_section_ in static mutexes.
- void ThreadSafeLazyInit();
-
- // Per https://blogs.msdn.microsoft.com/oldnewthing/20040223-00/?p=40503,
- // we assume that 0 is an invalid value for thread IDs.
- unsigned int owner_thread_id_;
-
- // For static mutexes, we rely on these members being initialized to zeros
- // by the linker.
- MutexType type_;
- long critical_section_init_phase_; // NOLINT
- GTEST_CRITICAL_SECTION* critical_section_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
-};
-
-# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
- extern ::testing::internal::Mutex mutex
-
-# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
- ::testing::internal::Mutex mutex(::testing::internal::Mutex::kStaticMutex)
-
-// We cannot name this class MutexLock because the ctor declaration would
-// conflict with a macro named MutexLock, which is defined on some
-// platforms. That macro is used as a defensive measure to prevent against
-// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
-// "MutexLock l(&mu)". Hence the typedef trick below.
-class GTestMutexLock {
- public:
- explicit GTestMutexLock(Mutex* mutex)
- : mutex_(mutex) { mutex_->Lock(); }
-
- ~GTestMutexLock() { mutex_->Unlock(); }
-
- private:
- Mutex* const mutex_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
-};
-
-typedef GTestMutexLock MutexLock;
-
-// Base class for ValueHolder<T>. Allows a caller to hold and delete a value
-// without knowing its type.
-class ThreadLocalValueHolderBase {
- public:
- virtual ~ThreadLocalValueHolderBase() {}
-};
-
-// Provides a way for a thread to send notifications to a ThreadLocal
-// regardless of its parameter type.
-class ThreadLocalBase {
- public:
- // Creates a new ValueHolder<T> object holding a default value passed to
- // this ThreadLocal<T>'s constructor and returns it. It is the caller's
- // responsibility not to call this when the ThreadLocal<T> instance already
- // has a value on the current thread.
- virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const = 0;
-
- protected:
- ThreadLocalBase() {}
- virtual ~ThreadLocalBase() {}
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocalBase);
-};
-
-// Maps a thread to a set of ThreadLocals that have values instantiated on that
-// thread and notifies them when the thread exits. A ThreadLocal instance is
-// expected to persist until all threads it has values on have terminated.
-class GTEST_API_ ThreadLocalRegistry {
- public:
- // Registers thread_local_instance as having value on the current thread.
- // Returns a value that can be used to identify the thread from other threads.
- static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
- const ThreadLocalBase* thread_local_instance);
-
- // Invoked when a ThreadLocal instance is destroyed.
- static void OnThreadLocalDestroyed(
- const ThreadLocalBase* thread_local_instance);
-};
-
-class GTEST_API_ ThreadWithParamBase {
- public:
- void Join();
-
- protected:
- class Runnable {
- public:
- virtual ~Runnable() {}
- virtual void Run() = 0;
- };
-
- ThreadWithParamBase(Runnable *runnable, Notification* thread_can_start);
- virtual ~ThreadWithParamBase();
-
- private:
- AutoHandle thread_;
-};
-
-// Helper class for testing Google Test's multi-threading constructs.
-template <typename T>
-class ThreadWithParam : public ThreadWithParamBase {
- public:
- typedef void UserThreadFunc(T);
-
- ThreadWithParam(UserThreadFunc* func, T param, Notification* thread_can_start)
- : ThreadWithParamBase(new RunnableImpl(func, param), thread_can_start) {
- }
- virtual ~ThreadWithParam() {}
-
- private:
- class RunnableImpl : public Runnable {
- public:
- RunnableImpl(UserThreadFunc* func, T param)
- : func_(func),
- param_(param) {
- }
- virtual ~RunnableImpl() {}
- virtual void Run() {
- func_(param_);
- }
-
- private:
- UserThreadFunc* const func_;
- const T param_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(RunnableImpl);
- };
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
-};
-
-// Implements thread-local storage on Windows systems.
-//
-// // Thread 1
-// ThreadLocal<int> tl(100); // 100 is the default value for each thread.
-//
-// // Thread 2
-// tl.set(150); // Changes the value for thread 2 only.
-// EXPECT_EQ(150, tl.get());
-//
-// // Thread 1
-// EXPECT_EQ(100, tl.get()); // In thread 1, tl has the original value.
-// tl.set(200);
-// EXPECT_EQ(200, tl.get());
-//
-// The template type argument T must have a public copy constructor.
-// In addition, the default ThreadLocal constructor requires T to have
-// a public default constructor.
-//
-// The users of a TheadLocal instance have to make sure that all but one
-// threads (including the main one) using that instance have exited before
-// destroying it. Otherwise, the per-thread objects managed for them by the
-// ThreadLocal instance are not guaranteed to be destroyed on all platforms.
-//
-// Google Test only uses global ThreadLocal objects. That means they
-// will die after main() has returned. Therefore, no per-thread
-// object managed by Google Test will be leaked as long as all threads
-// using Google Test have exited when main() returns.
-template <typename T>
-class ThreadLocal : public ThreadLocalBase {
- public:
- ThreadLocal() : default_factory_(new DefaultValueHolderFactory()) {}
- explicit ThreadLocal(const T& value)
- : default_factory_(new InstanceValueHolderFactory(value)) {}
-
- ~ThreadLocal() { ThreadLocalRegistry::OnThreadLocalDestroyed(this); }
-
- T* pointer() { return GetOrCreateValue(); }
- const T* pointer() const { return GetOrCreateValue(); }
- const T& get() const { return *pointer(); }
- void set(const T& value) { *pointer() = value; }
-
- private:
- // Holds a value of T. Can be deleted via its base class without the caller
- // knowing the type of T.
- class ValueHolder : public ThreadLocalValueHolderBase {
- public:
- ValueHolder() : value_() {}
- explicit ValueHolder(const T& value) : value_(value) {}
-
- T* pointer() { return &value_; }
-
- private:
- T value_;
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
- };
-
-
- T* GetOrCreateValue() const {
- return static_cast<ValueHolder*>(
- ThreadLocalRegistry::GetValueOnCurrentThread(this))->pointer();
- }
-
- virtual ThreadLocalValueHolderBase* NewValueForCurrentThread() const {
- return default_factory_->MakeNewHolder();
- }
-
- class ValueHolderFactory {
- public:
- ValueHolderFactory() {}
- virtual ~ValueHolderFactory() {}
- virtual ValueHolder* MakeNewHolder() const = 0;
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
- };
-
- class DefaultValueHolderFactory : public ValueHolderFactory {
- public:
- DefaultValueHolderFactory() {}
- virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); }
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
- };
-
- class InstanceValueHolderFactory : public ValueHolderFactory {
- public:
- explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
- virtual ValueHolder* MakeNewHolder() const {
- return new ValueHolder(value_);
- }
-
- private:
- const T value_; // The value for each thread.
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
- };
-
- std::unique_ptr<ValueHolderFactory> default_factory_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
-};
-
-# elif GTEST_HAS_PTHREAD
-
-// MutexBase and Mutex implement mutex on pthreads-based platforms.
-class MutexBase {
- public:
- // Acquires this mutex.
- void Lock() {
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
- owner_ = pthread_self();
- has_owner_ = true;
- }
-
- // Releases this mutex.
- void Unlock() {
- // Since the lock is being released the owner_ field should no longer be
- // considered valid. We don't protect writing to has_owner_ here, as it's
- // the caller's responsibility to ensure that the current thread holds the
- // mutex when this is called.
- has_owner_ = false;
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
- }
-
- // Does nothing if the current thread holds the mutex. Otherwise, crashes
- // with high probability.
- void AssertHeld() const {
- GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
- << "The current thread is not holding the mutex @" << this;
- }
-
- // A static mutex may be used before main() is entered. It may even
- // be used before the dynamic initialization stage. Therefore we
- // must be able to initialize a static mutex object at link time.
- // This means MutexBase has to be a POD and its member variables
- // have to be public.
- public:
- pthread_mutex_t mutex_; // The underlying pthread mutex.
- // has_owner_ indicates whether the owner_ field below contains a valid thread
- // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
- // accesses to the owner_ field should be protected by a check of this field.
- // An alternative might be to memset() owner_ to all zeros, but there's no
- // guarantee that a zero'd pthread_t is necessarily invalid or even different
- // from pthread_self().
- bool has_owner_;
- pthread_t owner_; // The thread holding the mutex.
-};
-
-// Forward-declares a static mutex.
-# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
- extern ::testing::internal::MutexBase mutex
-
-// Defines and statically (i.e. at link time) initializes a static mutex.
-// The initialization list here does not explicitly initialize each field,
-// instead relying on default initialization for the unspecified fields. In
-// particular, the owner_ field (a pthread_t) is not explicitly initialized.
-// This allows initialization to work whether pthread_t is a scalar or struct.
-// The flag -Wmissing-field-initializers must not be specified for this to work.
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
- ::testing::internal::MutexBase mutex = {PTHREAD_MUTEX_INITIALIZER, false, 0}
-
-// The Mutex class can only be used for mutexes created at runtime. It
-// shares its API with MutexBase otherwise.
-class Mutex : public MutexBase {
- public:
- Mutex() {
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, nullptr));
- has_owner_ = false;
- }
- ~Mutex() {
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
- }
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
-};
-
-// We cannot name this class MutexLock because the ctor declaration would
-// conflict with a macro named MutexLock, which is defined on some
-// platforms. That macro is used as a defensive measure to prevent against
-// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
-// "MutexLock l(&mu)". Hence the typedef trick below.
-class GTestMutexLock {
- public:
- explicit GTestMutexLock(MutexBase* mutex)
- : mutex_(mutex) { mutex_->Lock(); }
-
- ~GTestMutexLock() { mutex_->Unlock(); }
-
- private:
- MutexBase* const mutex_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
-};
-
-typedef GTestMutexLock MutexLock;
-
-// Helpers for ThreadLocal.
-
-// pthread_key_create() requires DeleteThreadLocalValue() to have
-// C-linkage. Therefore it cannot be templatized to access
-// ThreadLocal<T>. Hence the need for class
-// ThreadLocalValueHolderBase.
-class ThreadLocalValueHolderBase {
- public:
- virtual ~ThreadLocalValueHolderBase() {}
-};
-
-// Called by pthread to delete thread-local data stored by
-// pthread_setspecific().
-extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
- delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
-}
-
-// Implements thread-local storage on pthreads-based systems.
-template <typename T>
-class GTEST_API_ ThreadLocal {
- public:
- ThreadLocal()
- : key_(CreateKey()), default_factory_(new DefaultValueHolderFactory()) {}
- explicit ThreadLocal(const T& value)
- : key_(CreateKey()),
- default_factory_(new InstanceValueHolderFactory(value)) {}
-
- ~ThreadLocal() {
- // Destroys the managed object for the current thread, if any.
- DeleteThreadLocalValue(pthread_getspecific(key_));
-
- // Releases resources associated with the key. This will *not*
- // delete managed objects for other threads.
- GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
- }
-
- T* pointer() { return GetOrCreateValue(); }
- const T* pointer() const { return GetOrCreateValue(); }
- const T& get() const { return *pointer(); }
- void set(const T& value) { *pointer() = value; }
-
- private:
- // Holds a value of type T.
- class ValueHolder : public ThreadLocalValueHolderBase {
- public:
- ValueHolder() : value_() {}
- explicit ValueHolder(const T& value) : value_(value) {}
-
- T* pointer() { return &value_; }
-
- private:
- T value_;
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
- };
-
- static pthread_key_t CreateKey() {
- pthread_key_t key;
- // When a thread exits, DeleteThreadLocalValue() will be called on
- // the object managed for that thread.
- GTEST_CHECK_POSIX_SUCCESS_(
- pthread_key_create(&key, &DeleteThreadLocalValue));
- return key;
- }
-
- T* GetOrCreateValue() const {
- ThreadLocalValueHolderBase* const holder =
- static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
- if (holder != nullptr) {
- return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
- }
-
- ValueHolder* const new_holder = default_factory_->MakeNewHolder();
- ThreadLocalValueHolderBase* const holder_base = new_holder;
- GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
- return new_holder->pointer();
- }
-
- class ValueHolderFactory {
- public:
- ValueHolderFactory() {}
- virtual ~ValueHolderFactory() {}
- virtual ValueHolder* MakeNewHolder() const = 0;
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolderFactory);
- };
-
- class DefaultValueHolderFactory : public ValueHolderFactory {
- public:
- DefaultValueHolderFactory() {}
- virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); }
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory);
- };
-
- class InstanceValueHolderFactory : public ValueHolderFactory {
- public:
- explicit InstanceValueHolderFactory(const T& value) : value_(value) {}
- virtual ValueHolder* MakeNewHolder() const {
- return new ValueHolder(value_);
- }
-
- private:
- const T value_; // The value for each thread.
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(InstanceValueHolderFactory);
- };
-
- // A key pthreads uses for looking up per-thread values.
- const pthread_key_t key_;
- std::unique_ptr<ValueHolderFactory> default_factory_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
-};
-
-# endif // GTEST_HAS_MUTEX_AND_THREAD_LOCAL_
-
-#else // GTEST_IS_THREADSAFE
-
-// A dummy implementation of synchronization primitives (mutex, lock,
-// and thread-local variable). Necessary for compiling Google Test where
-// mutex is not supported - using Google Test in multiple threads is not
-// supported on such platforms.
-
-class Mutex {
- public:
- Mutex() {}
- void Lock() {}
- void Unlock() {}
- void AssertHeld() const {}
-};
-
-# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
- extern ::testing::internal::Mutex mutex
-
-# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
-
-// We cannot name this class MutexLock because the ctor declaration would
-// conflict with a macro named MutexLock, which is defined on some
-// platforms. That macro is used as a defensive measure to prevent against
-// inadvertent misuses of MutexLock like "MutexLock(&mu)" rather than
-// "MutexLock l(&mu)". Hence the typedef trick below.
-class GTestMutexLock {
- public:
- explicit GTestMutexLock(Mutex*) {} // NOLINT
-};
-
-typedef GTestMutexLock MutexLock;
-
-template <typename T>
-class GTEST_API_ ThreadLocal {
- public:
- ThreadLocal() : value_() {}
- explicit ThreadLocal(const T& value) : value_(value) {}
- T* pointer() { return &value_; }
- const T* pointer() const { return &value_; }
- const T& get() const { return value_; }
- void set(const T& value) { value_ = value; }
- private:
- T value_;
-};
-
-#endif // GTEST_IS_THREADSAFE
-
-// Returns the number of threads running in the process, or 0 to indicate that
-// we cannot detect it.
-GTEST_API_ size_t GetThreadCount();
-
-template <bool B>
-using bool_constant = std::integral_constant<bool, B>;
-
-#if GTEST_OS_WINDOWS
-# define GTEST_PATH_SEP_ "\\"
-# define GTEST_HAS_ALT_PATH_SEP_ 1
-// The biggest signed integer type the compiler supports.
-typedef __int64 BiggestInt;
-#else
-# define GTEST_PATH_SEP_ "/"
-# define GTEST_HAS_ALT_PATH_SEP_ 0
-typedef long long BiggestInt; // NOLINT
-#endif // GTEST_OS_WINDOWS
-
-// Utilities for char.
-
-// isspace(int ch) and friends accept an unsigned char or EOF. char
-// may be signed, depending on the compiler (or compiler flags).
-// Therefore we need to cast a char to unsigned char before calling
-// isspace(), etc.
-
-inline bool IsAlpha(char ch) {
- return isalpha(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsAlNum(char ch) {
- return isalnum(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsDigit(char ch) {
- return isdigit(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsLower(char ch) {
- return islower(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsSpace(char ch) {
- return isspace(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsUpper(char ch) {
- return isupper(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsXDigit(char ch) {
- return isxdigit(static_cast<unsigned char>(ch)) != 0;
-}
-inline bool IsXDigit(wchar_t ch) {
- const unsigned char low_byte = static_cast<unsigned char>(ch);
- return ch == low_byte && isxdigit(low_byte) != 0;
-}
-
-inline char ToLower(char ch) {
- return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
-}
-inline char ToUpper(char ch) {
- return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
-}
-
-inline std::string StripTrailingSpaces(std::string str) {
- std::string::iterator it = str.end();
- while (it != str.begin() && IsSpace(*--it))
- it = str.erase(it);
- return str;
-}
-
-// The testing::internal::posix namespace holds wrappers for common
-// POSIX functions. These wrappers hide the differences between
-// Windows/MSVC and POSIX systems. Since some compilers define these
-// standard functions as macros, the wrapper cannot have the same name
-// as the wrapped function.
-
-namespace posix {
-
-// Functions with a different name on Windows.
-
-#if GTEST_OS_WINDOWS
-
-typedef struct _stat StatStruct;
-
-# ifdef __BORLANDC__
-inline int IsATTY(int fd) { return isatty(fd); }
-inline int StrCaseCmp(const char* s1, const char* s2) {
- return stricmp(s1, s2);
-}
-inline char* StrDup(const char* src) { return strdup(src); }
-# else // !__BORLANDC__
-# if GTEST_OS_WINDOWS_MOBILE
-inline int IsATTY(int /* fd */) { return 0; }
-# else
-inline int IsATTY(int fd) { return _isatty(fd); }
-# endif // GTEST_OS_WINDOWS_MOBILE
-inline int StrCaseCmp(const char* s1, const char* s2) {
- return _stricmp(s1, s2);
-}
-inline char* StrDup(const char* src) { return _strdup(src); }
-# endif // __BORLANDC__
-
-# if GTEST_OS_WINDOWS_MOBILE
-inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
-// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
-// time and thus not defined there.
-# else
-inline int FileNo(FILE* file) { return _fileno(file); }
-inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
-inline int RmDir(const char* dir) { return _rmdir(dir); }
-inline bool IsDir(const StatStruct& st) {
- return (_S_IFDIR & st.st_mode) != 0;
-}
-# endif // GTEST_OS_WINDOWS_MOBILE
-
-#else
-
-typedef struct stat StatStruct;
-
-inline int FileNo(FILE* file) { return fileno(file); }
-inline int IsATTY(int fd) { return isatty(fd); }
-inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
-inline int StrCaseCmp(const char* s1, const char* s2) {
- return strcasecmp(s1, s2);
-}
-inline char* StrDup(const char* src) { return strdup(src); }
-inline int RmDir(const char* dir) { return rmdir(dir); }
-inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
-
-#endif // GTEST_OS_WINDOWS
-
-// Functions deprecated by MSVC 8.0.
-
-GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
-
-inline const char* StrNCpy(char* dest, const char* src, size_t n) {
- return strncpy(dest, src, n);
-}
-
-// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
-// StrError() aren't needed on Windows CE at this time and thus not
-// defined there.
-
-#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
-inline int ChDir(const char* dir) { return chdir(dir); }
-#endif
-inline FILE* FOpen(const char* path, const char* mode) {
- return fopen(path, mode);
-}
-#if !GTEST_OS_WINDOWS_MOBILE
-inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
- return freopen(path, mode, stream);
-}
-inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
-#endif
-inline int FClose(FILE* fp) { return fclose(fp); }
-#if !GTEST_OS_WINDOWS_MOBILE
-inline int Read(int fd, void* buf, unsigned int count) {
- return static_cast<int>(read(fd, buf, count));
-}
-inline int Write(int fd, const void* buf, unsigned int count) {
- return static_cast<int>(write(fd, buf, count));
-}
-inline int Close(int fd) { return close(fd); }
-inline const char* StrError(int errnum) { return strerror(errnum); }
-#endif
-inline const char* GetEnv(const char* name) {
-#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
- // We are on Windows CE, which has no environment variables.
- static_cast<void>(name); // To prevent 'unused argument' warning.
- return nullptr;
-#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
- // Environment variables which we programmatically clear will be set to the
- // empty string rather than unset (NULL). Handle that case.
- const char* const env = getenv(name);
- return (env != nullptr && env[0] != '\0') ? env : nullptr;
-#else
- return getenv(name);
-#endif
-}
-
-GTEST_DISABLE_MSC_DEPRECATED_POP_()
-
-#if GTEST_OS_WINDOWS_MOBILE
-// Windows CE has no C library. The abort() function is used in
-// several places in Google Test. This implementation provides a reasonable
-// imitation of standard behaviour.
-[[noreturn]] void Abort();
-#else
-[[noreturn]] inline void Abort() { abort(); }
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-} // namespace posix
-
-// MSVC "deprecates" snprintf and issues warnings wherever it is used. In
-// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
-// MSVC-based platforms. We map the GTEST_SNPRINTF_ macro to the appropriate
-// function in order to achieve that. We use macro definition here because
-// snprintf is a variadic function.
-#if _MSC_VER && !GTEST_OS_WINDOWS_MOBILE
-// MSVC 2005 and above support variadic macros.
-# define GTEST_SNPRINTF_(buffer, size, format, ...) \
- _snprintf_s(buffer, size, size, format, __VA_ARGS__)
-#elif defined(_MSC_VER)
-// Windows CE does not define _snprintf_s
-# define GTEST_SNPRINTF_ _snprintf
-#else
-# define GTEST_SNPRINTF_ snprintf
-#endif
-
-// The maximum number a BiggestInt can represent. This definition
-// works no matter BiggestInt is represented in one's complement or
-// two's complement.
-//
-// We cannot rely on numeric_limits in STL, as __int64 and long long
-// are not part of standard C++ and numeric_limits doesn't need to be
-// defined for them.
-const BiggestInt kMaxBiggestInt =
- ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
-
-// This template class serves as a compile-time function from size to
-// type. It maps a size in bytes to a primitive type with that
-// size. e.g.
-//
-// TypeWithSize<4>::UInt
-//
-// is typedef-ed to be unsigned int (unsigned integer made up of 4
-// bytes).
-//
-// Such functionality should belong to STL, but I cannot find it
-// there.
-//
-// Google Test uses this class in the implementation of floating-point
-// comparison.
-//
-// For now it only handles UInt (unsigned int) as that's all Google Test
-// needs. Other types can be easily added in the future if need
-// arises.
-template <size_t size>
-class TypeWithSize {
- public:
- // This prevents the user from using TypeWithSize<N> with incorrect
- // values of N.
- typedef void UInt;
-};
-
-// The specialization for size 4.
-template <>
-class TypeWithSize<4> {
- public:
- // unsigned int has size 4 in both gcc and MSVC.
- //
- // As base/basictypes.h doesn't compile on Windows, we cannot use
- // uint32, uint64, and etc here.
- typedef int Int;
- typedef unsigned int UInt;
-};
-
-// The specialization for size 8.
-template <>
-class TypeWithSize<8> {
- public:
-#if GTEST_OS_WINDOWS
- typedef __int64 Int;
- typedef unsigned __int64 UInt;
-#else
- typedef long long Int; // NOLINT
- typedef unsigned long long UInt; // NOLINT
-#endif // GTEST_OS_WINDOWS
-};
-
-// Integer types of known sizes.
-typedef TypeWithSize<4>::Int Int32;
-typedef TypeWithSize<4>::UInt UInt32;
-typedef TypeWithSize<8>::Int Int64;
-typedef TypeWithSize<8>::UInt UInt64;
-typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds.
-
-// Utilities for command line flags and environment variables.
-
-// Macro for referencing flags.
-#if !defined(GTEST_FLAG)
-# define GTEST_FLAG(name) FLAGS_gtest_##name
-#endif // !defined(GTEST_FLAG)
-
-#if !defined(GTEST_USE_OWN_FLAGFILE_FLAG_)
-# define GTEST_USE_OWN_FLAGFILE_FLAG_ 1
-#endif // !defined(GTEST_USE_OWN_FLAGFILE_FLAG_)
-
-#if !defined(GTEST_DECLARE_bool_)
-# define GTEST_FLAG_SAVER_ ::testing::internal::GTestFlagSaver
-
-// Macros for declaring flags.
-# define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
-# define GTEST_DECLARE_int32_(name) \
- GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
-# define GTEST_DECLARE_string_(name) \
- GTEST_API_ extern ::std::string GTEST_FLAG(name)
-
-// Macros for defining flags.
-# define GTEST_DEFINE_bool_(name, default_val, doc) \
- GTEST_API_ bool GTEST_FLAG(name) = (default_val)
-# define GTEST_DEFINE_int32_(name, default_val, doc) \
- GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
-# define GTEST_DEFINE_string_(name, default_val, doc) \
- GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
-
-#endif // !defined(GTEST_DECLARE_bool_)
-
-// Thread annotations
-#if !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
-# define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
-# define GTEST_LOCK_EXCLUDED_(locks)
-#endif // !defined(GTEST_EXCLUSIVE_LOCK_REQUIRED_)
-
-// Parses 'str' for a 32-bit signed integer. If successful, writes the result
-// to *value and returns true; otherwise leaves *value unchanged and returns
-// false.
-bool ParseInt32(const Message& src_text, const char* str, Int32* value);
-
-// Parses a bool/Int32/string from the environment variable
-// corresponding to the given Google Test flag.
-bool BoolFromGTestEnv(const char* flag, bool default_val);
-GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
-std::string OutputFlagAlsoCheckEnvVar();
-const char* StringFromGTestEnv(const char* flag, const char* default_val);
-
-} // namespace internal
-} // namespace testing
-
-#if !defined(GTEST_INTERNAL_DEPRECATED)
-
-// Internal Macro to mark an API deprecated, for googletest usage only
-// Usage: class GTEST_INTERNAL_DEPRECATED(message) MyClass or
-// GTEST_INTERNAL_DEPRECATED(message) <return_type> myFunction(); Every usage of
-// a deprecated entity will trigger a warning when compiled with
-// `-Wdeprecated-declarations` option (clang, gcc, any __GNUC__ compiler).
-// For msvc /W3 option will need to be used
-// Note that for 'other' compilers this macro evaluates to nothing to prevent
-// compilations errors.
-#if defined(_MSC_VER)
-#define GTEST_INTERNAL_DEPRECATED(message) __declspec(deprecated(message))
-#elif defined(__GNUC__)
-#define GTEST_INTERNAL_DEPRECATED(message) __attribute__((deprecated(message)))
-#else
-#define GTEST_INTERNAL_DEPRECATED(message)
-#endif
-
-#endif // !defined(GTEST_INTERNAL_DEPRECATED)
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file declares the String class and functions used internally by
-// Google Test. They are subject to change without notice. They should not used
-// by code external to Google Test.
-//
-// This header file is #included by gtest-internal.h.
-// It should not be #included by other files.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
-
-#ifdef __BORLANDC__
-// string.h is not guaranteed to provide strcpy on C++ Builder.
-# include <mem.h>
-#endif
-
-#include <string.h>
-#include <string>
-
-#include "gtest/internal/gtest-port.h"
-
-namespace testing {
-namespace internal {
-
-// String - an abstract class holding static string utilities.
-class GTEST_API_ String {
- public:
- // Static utility methods
-
- // Clones a 0-terminated C string, allocating memory using new. The
- // caller is responsible for deleting the return value using
- // delete[]. Returns the cloned string, or NULL if the input is
- // NULL.
- //
- // This is different from strdup() in string.h, which allocates
- // memory using malloc().
- static const char* CloneCString(const char* c_str);
-
-#if GTEST_OS_WINDOWS_MOBILE
- // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
- // able to pass strings to Win32 APIs on CE we need to convert them
- // to 'Unicode', UTF-16.
-
- // Creates a UTF-16 wide string from the given ANSI string, allocating
- // memory using new. The caller is responsible for deleting the return
- // value using delete[]. Returns the wide string, or NULL if the
- // input is NULL.
- //
- // The wide string is created using the ANSI codepage (CP_ACP) to
- // match the behaviour of the ANSI versions of Win32 calls and the
- // C runtime.
- static LPCWSTR AnsiToUtf16(const char* c_str);
-
- // Creates an ANSI string from the given wide string, allocating
- // memory using new. The caller is responsible for deleting the return
- // value using delete[]. Returns the ANSI string, or NULL if the
- // input is NULL.
- //
- // The returned string is created using the ANSI codepage (CP_ACP) to
- // match the behaviour of the ANSI versions of Win32 calls and the
- // C runtime.
- static const char* Utf16ToAnsi(LPCWSTR utf16_str);
-#endif
-
- // Compares two C strings. Returns true if and only if they have the same
- // content.
- //
- // Unlike strcmp(), this function can handle NULL argument(s). A
- // NULL C string is considered different to any non-NULL C string,
- // including the empty string.
- static bool CStringEquals(const char* lhs, const char* rhs);
-
- // Converts a wide C string to a String using the UTF-8 encoding.
- // NULL will be converted to "(null)". If an error occurred during
- // the conversion, "(failed to convert from wide string)" is
- // returned.
- static std::string ShowWideCString(const wchar_t* wide_c_str);
-
- // Compares two wide C strings. Returns true if and only if they have the
- // same content.
- //
- // Unlike wcscmp(), this function can handle NULL argument(s). A
- // NULL C string is considered different to any non-NULL C string,
- // including the empty string.
- static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
-
- // Compares two C strings, ignoring case. Returns true if and only if
- // they have the same content.
- //
- // Unlike strcasecmp(), this function can handle NULL argument(s).
- // A NULL C string is considered different to any non-NULL C string,
- // including the empty string.
- static bool CaseInsensitiveCStringEquals(const char* lhs,
- const char* rhs);
-
- // Compares two wide C strings, ignoring case. Returns true if and only if
- // they have the same content.
- //
- // Unlike wcscasecmp(), this function can handle NULL argument(s).
- // A NULL C string is considered different to any non-NULL wide C string,
- // including the empty string.
- // NB: The implementations on different platforms slightly differ.
- // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
- // environment variable. On GNU platform this method uses wcscasecmp
- // which compares according to LC_CTYPE category of the current locale.
- // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
- // current locale.
- static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
- const wchar_t* rhs);
-
- // Returns true if and only if the given string ends with the given suffix,
- // ignoring case. Any string is considered to end with an empty suffix.
- static bool EndsWithCaseInsensitive(
- const std::string& str, const std::string& suffix);
-
- // Formats an int value as "%02d".
- static std::string FormatIntWidth2(int value); // "%02d" for width == 2
-
- // Formats an int value as "%X".
- static std::string FormatHexInt(int value);
-
- // Formats an int value as "%X".
- static std::string FormatHexUInt32(UInt32 value);
-
- // Formats a byte as "%02X".
- static std::string FormatByte(unsigned char value);
-
- private:
- String(); // Not meant to be instantiated.
-}; // class String
-
-// Gets the content of the stringstream's buffer as an std::string. Each '\0'
-// character in the buffer is replaced with "\\0".
-GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
-
-} // namespace internal
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+++ /dev/null
-// This file was GENERATED by command:
-// pump.py gtest-type-util.h.pump
-// DO NOT EDIT BY HAND!!!
-
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Type utilities needed for implementing typed and type-parameterized
-// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
-//
-// Currently we support at most 50 types in a list, and at most 50
-// type-parameterized tests in one type-parameterized test suite.
-// Please contact googletestframework@googlegroups.com if you need
-// more.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-
-#include "gtest/internal/gtest-port.h"
-
-// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
-// libstdc++ (which is where cxxabi.h comes from).
-# if GTEST_HAS_CXXABI_H_
-# include <cxxabi.h>
-# elif defined(__HP_aCC)
-# include <acxx_demangle.h>
-# endif // GTEST_HASH_CXXABI_H_
-
-namespace testing {
-namespace internal {
-
-// Canonicalizes a given name with respect to the Standard C++ Library.
-// This handles removing the inline namespace within `std` that is
-// used by various standard libraries (e.g., `std::__1`). Names outside
-// of namespace std are returned unmodified.
-inline std::string CanonicalizeForStdLibVersioning(std::string s) {
- static const char prefix[] = "std::__";
- if (s.compare(0, strlen(prefix), prefix) == 0) {
- std::string::size_type end = s.find("::", strlen(prefix));
- if (end != s.npos) {
- // Erase everything between the initial `std` and the second `::`.
- s.erase(strlen("std"), end - strlen("std"));
- }
- }
- return s;
-}
-
-// GetTypeName<T>() returns a human-readable name of type T.
-// NB: This function is also used in Google Mock, so don't move it inside of
-// the typed-test-only section below.
-template <typename T>
-std::string GetTypeName() {
-# if GTEST_HAS_RTTI
-
- const char* const name = typeid(T).name();
-# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
- int status = 0;
- // gcc's implementation of typeid(T).name() mangles the type name,
- // so we have to demangle it.
-# if GTEST_HAS_CXXABI_H_
- using abi::__cxa_demangle;
-# endif // GTEST_HAS_CXXABI_H_
- char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
- const std::string name_str(status == 0 ? readable_name : name);
- free(readable_name);
- return CanonicalizeForStdLibVersioning(name_str);
-# else
- return name;
-# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
-
-# else
-
- return "<type>";
-
-# endif // GTEST_HAS_RTTI
-}
-
-#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
-// A unique type used as the default value for the arguments of class
-// template Types. This allows us to simulate variadic templates
-// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
-// support directly.
-struct None {};
-
-// The following family of struct and struct templates are used to
-// represent type lists. In particular, TypesN<T1, T2, ..., TN>
-// represents a type list with N types (T1, T2, ..., and TN) in it.
-// Except for Types0, every struct in the family has two member types:
-// Head for the first type in the list, and Tail for the rest of the
-// list.
-
-// The empty type list.
-struct Types0 {};
-
-// Type lists of length 1, 2, 3, and so on.
-
-template <typename T1>
-struct Types1 {
- typedef T1 Head;
- typedef Types0 Tail;
-};
-template <typename T1, typename T2>
-struct Types2 {
- typedef T1 Head;
- typedef Types1<T2> Tail;
-};
-
-template <typename T1, typename T2, typename T3>
-struct Types3 {
- typedef T1 Head;
- typedef Types2<T2, T3> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4>
-struct Types4 {
- typedef T1 Head;
- typedef Types3<T2, T3, T4> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-struct Types5 {
- typedef T1 Head;
- typedef Types4<T2, T3, T4, T5> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-struct Types6 {
- typedef T1 Head;
- typedef Types5<T2, T3, T4, T5, T6> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7>
-struct Types7 {
- typedef T1 Head;
- typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8>
-struct Types8 {
- typedef T1 Head;
- typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9>
-struct Types9 {
- typedef T1 Head;
- typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10>
-struct Types10 {
- typedef T1 Head;
- typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11>
-struct Types11 {
- typedef T1 Head;
- typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12>
-struct Types12 {
- typedef T1 Head;
- typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13>
-struct Types13 {
- typedef T1 Head;
- typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14>
-struct Types14 {
- typedef T1 Head;
- typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15>
-struct Types15 {
- typedef T1 Head;
- typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16>
-struct Types16 {
- typedef T1 Head;
- typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17>
-struct Types17 {
- typedef T1 Head;
- typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18>
-struct Types18 {
- typedef T1 Head;
- typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19>
-struct Types19 {
- typedef T1 Head;
- typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20>
-struct Types20 {
- typedef T1 Head;
- typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21>
-struct Types21 {
- typedef T1 Head;
- typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22>
-struct Types22 {
- typedef T1 Head;
- typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23>
-struct Types23 {
- typedef T1 Head;
- typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24>
-struct Types24 {
- typedef T1 Head;
- typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25>
-struct Types25 {
- typedef T1 Head;
- typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26>
-struct Types26 {
- typedef T1 Head;
- typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27>
-struct Types27 {
- typedef T1 Head;
- typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28>
-struct Types28 {
- typedef T1 Head;
- typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29>
-struct Types29 {
- typedef T1 Head;
- typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30>
-struct Types30 {
- typedef T1 Head;
- typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31>
-struct Types31 {
- typedef T1 Head;
- typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32>
-struct Types32 {
- typedef T1 Head;
- typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33>
-struct Types33 {
- typedef T1 Head;
- typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34>
-struct Types34 {
- typedef T1 Head;
- typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35>
-struct Types35 {
- typedef T1 Head;
- typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36>
-struct Types36 {
- typedef T1 Head;
- typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37>
-struct Types37 {
- typedef T1 Head;
- typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38>
-struct Types38 {
- typedef T1 Head;
- typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39>
-struct Types39 {
- typedef T1 Head;
- typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40>
-struct Types40 {
- typedef T1 Head;
- typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41>
-struct Types41 {
- typedef T1 Head;
- typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42>
-struct Types42 {
- typedef T1 Head;
- typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43>
-struct Types43 {
- typedef T1 Head;
- typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44>
-struct Types44 {
- typedef T1 Head;
- typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45>
-struct Types45 {
- typedef T1 Head;
- typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46>
-struct Types46 {
- typedef T1 Head;
- typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47>
-struct Types47 {
- typedef T1 Head;
- typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46, T47> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48>
-struct Types48 {
- typedef T1 Head;
- typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46, T47, T48> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48, typename T49>
-struct Types49 {
- typedef T1 Head;
- typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46, T47, T48, T49> Tail;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48, typename T49, typename T50>
-struct Types50 {
- typedef T1 Head;
- typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46, T47, T48, T49, T50> Tail;
-};
-
-
-} // namespace internal
-
-// We don't want to require the users to write TypesN<...> directly,
-// as that would require them to count the length. Types<...> is much
-// easier to write, but generates horrible messages when there is a
-// compiler error, as gcc insists on printing out each template
-// argument, even if it has the default value (this means Types<int>
-// will appear as Types<int, None, None, ..., None> in the compiler
-// errors).
-//
-// Our solution is to combine the best part of the two approaches: a
-// user would write Types<T1, ..., TN>, and Google Test will translate
-// that to TypesN<T1, ..., TN> internally to make error messages
-// readable. The translation is done by the 'type' member of the
-// Types template.
-template <typename T1 = internal::None, typename T2 = internal::None,
- typename T3 = internal::None, typename T4 = internal::None,
- typename T5 = internal::None, typename T6 = internal::None,
- typename T7 = internal::None, typename T8 = internal::None,
- typename T9 = internal::None, typename T10 = internal::None,
- typename T11 = internal::None, typename T12 = internal::None,
- typename T13 = internal::None, typename T14 = internal::None,
- typename T15 = internal::None, typename T16 = internal::None,
- typename T17 = internal::None, typename T18 = internal::None,
- typename T19 = internal::None, typename T20 = internal::None,
- typename T21 = internal::None, typename T22 = internal::None,
- typename T23 = internal::None, typename T24 = internal::None,
- typename T25 = internal::None, typename T26 = internal::None,
- typename T27 = internal::None, typename T28 = internal::None,
- typename T29 = internal::None, typename T30 = internal::None,
- typename T31 = internal::None, typename T32 = internal::None,
- typename T33 = internal::None, typename T34 = internal::None,
- typename T35 = internal::None, typename T36 = internal::None,
- typename T37 = internal::None, typename T38 = internal::None,
- typename T39 = internal::None, typename T40 = internal::None,
- typename T41 = internal::None, typename T42 = internal::None,
- typename T43 = internal::None, typename T44 = internal::None,
- typename T45 = internal::None, typename T46 = internal::None,
- typename T47 = internal::None, typename T48 = internal::None,
- typename T49 = internal::None, typename T50 = internal::None>
-struct Types {
- typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
-};
-
-template <>
-struct Types<internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types0 type;
-};
-template <typename T1>
-struct Types<T1, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types1<T1> type;
-};
-template <typename T1, typename T2>
-struct Types<T1, T2, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types2<T1, T2> type;
-};
-template <typename T1, typename T2, typename T3>
-struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types3<T1, T2, T3> type;
-};
-template <typename T1, typename T2, typename T3, typename T4>
-struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types4<T1, T2, T3, T4> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types5<T1, T2, T3, T4, T5> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6>
-struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7>
-struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
- T12> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
- T26> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
- T40> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None, internal::None> {
- typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- internal::None, internal::None, internal::None, internal::None,
- internal::None, internal::None> {
- typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
- internal::None, internal::None, internal::None, internal::None,
- internal::None> {
- typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
- T46, internal::None, internal::None, internal::None, internal::None> {
- typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
- T46, T47, internal::None, internal::None, internal::None> {
- typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46, T47> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
- T46, T47, T48, internal::None, internal::None> {
- typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46, T47, T48> type;
-};
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48, typename T49>
-struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
- T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
- T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
- T46, T47, T48, T49, internal::None> {
- typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
-};
-
-namespace internal {
-
-# define GTEST_TEMPLATE_ template <typename T> class
-
-// The template "selector" struct TemplateSel<Tmpl> is used to
-// represent Tmpl, which must be a class template with one type
-// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
-// as the type Tmpl<T>. This allows us to actually instantiate the
-// template "selected" by TemplateSel<Tmpl>.
-//
-// This trick is necessary for simulating typedef for class templates,
-// which C++ doesn't support directly.
-template <GTEST_TEMPLATE_ Tmpl>
-struct TemplateSel {
- template <typename T>
- struct Bind {
- typedef Tmpl<T> type;
- };
-};
-
-# define GTEST_BIND_(TmplSel, T) \
- TmplSel::template Bind<T>::type
-
-// A unique struct template used as the default value for the
-// arguments of class template Templates. This allows us to simulate
-// variadic templates (e.g. Templates<int>, Templates<int, double>,
-// and etc), which C++ doesn't support directly.
-template <typename T>
-struct NoneT {};
-
-// The following family of struct and struct templates are used to
-// represent template lists. In particular, TemplatesN<T1, T2, ...,
-// TN> represents a list of N templates (T1, T2, ..., and TN). Except
-// for Templates0, every struct in the family has two member types:
-// Head for the selector of the first template in the list, and Tail
-// for the rest of the list.
-
-// The empty template list.
-struct Templates0 {};
-
-// Template lists of length 1, 2, 3, and so on.
-
-template <GTEST_TEMPLATE_ T1>
-struct Templates1 {
- typedef TemplateSel<T1> Head;
- typedef Templates0 Tail;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
-struct Templates2 {
- typedef TemplateSel<T1> Head;
- typedef Templates1<T2> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
-struct Templates3 {
- typedef TemplateSel<T1> Head;
- typedef Templates2<T2, T3> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4>
-struct Templates4 {
- typedef TemplateSel<T1> Head;
- typedef Templates3<T2, T3, T4> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
-struct Templates5 {
- typedef TemplateSel<T1> Head;
- typedef Templates4<T2, T3, T4, T5> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
-struct Templates6 {
- typedef TemplateSel<T1> Head;
- typedef Templates5<T2, T3, T4, T5, T6> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7>
-struct Templates7 {
- typedef TemplateSel<T1> Head;
- typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
-struct Templates8 {
- typedef TemplateSel<T1> Head;
- typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
-struct Templates9 {
- typedef TemplateSel<T1> Head;
- typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10>
-struct Templates10 {
- typedef TemplateSel<T1> Head;
- typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
-struct Templates11 {
- typedef TemplateSel<T1> Head;
- typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
-struct Templates12 {
- typedef TemplateSel<T1> Head;
- typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13>
-struct Templates13 {
- typedef TemplateSel<T1> Head;
- typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
-struct Templates14 {
- typedef TemplateSel<T1> Head;
- typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
-struct Templates15 {
- typedef TemplateSel<T1> Head;
- typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16>
-struct Templates16 {
- typedef TemplateSel<T1> Head;
- typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
-struct Templates17 {
- typedef TemplateSel<T1> Head;
- typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
-struct Templates18 {
- typedef TemplateSel<T1> Head;
- typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19>
-struct Templates19 {
- typedef TemplateSel<T1> Head;
- typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
-struct Templates20 {
- typedef TemplateSel<T1> Head;
- typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
-struct Templates21 {
- typedef TemplateSel<T1> Head;
- typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22>
-struct Templates22 {
- typedef TemplateSel<T1> Head;
- typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
-struct Templates23 {
- typedef TemplateSel<T1> Head;
- typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
-struct Templates24 {
- typedef TemplateSel<T1> Head;
- typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25>
-struct Templates25 {
- typedef TemplateSel<T1> Head;
- typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
-struct Templates26 {
- typedef TemplateSel<T1> Head;
- typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
-struct Templates27 {
- typedef TemplateSel<T1> Head;
- typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28>
-struct Templates28 {
- typedef TemplateSel<T1> Head;
- typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
-struct Templates29 {
- typedef TemplateSel<T1> Head;
- typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
-struct Templates30 {
- typedef TemplateSel<T1> Head;
- typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31>
-struct Templates31 {
- typedef TemplateSel<T1> Head;
- typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
-struct Templates32 {
- typedef TemplateSel<T1> Head;
- typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
-struct Templates33 {
- typedef TemplateSel<T1> Head;
- typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34>
-struct Templates34 {
- typedef TemplateSel<T1> Head;
- typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
-struct Templates35 {
- typedef TemplateSel<T1> Head;
- typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
-struct Templates36 {
- typedef TemplateSel<T1> Head;
- typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37>
-struct Templates37 {
- typedef TemplateSel<T1> Head;
- typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
-struct Templates38 {
- typedef TemplateSel<T1> Head;
- typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
-struct Templates39 {
- typedef TemplateSel<T1> Head;
- typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40>
-struct Templates40 {
- typedef TemplateSel<T1> Head;
- typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
-struct Templates41 {
- typedef TemplateSel<T1> Head;
- typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
-struct Templates42 {
- typedef TemplateSel<T1> Head;
- typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43>
-struct Templates43 {
- typedef TemplateSel<T1> Head;
- typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
-struct Templates44 {
- typedef TemplateSel<T1> Head;
- typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
-struct Templates45 {
- typedef TemplateSel<T1> Head;
- typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44, T45> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46>
-struct Templates46 {
- typedef TemplateSel<T1> Head;
- typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44, T45, T46> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
-struct Templates47 {
- typedef TemplateSel<T1> Head;
- typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44, T45, T46, T47> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
-struct Templates48 {
- typedef TemplateSel<T1> Head;
- typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44, T45, T46, T47, T48> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
- GTEST_TEMPLATE_ T49>
-struct Templates49 {
- typedef TemplateSel<T1> Head;
- typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44, T45, T46, T47, T48, T49> Tail;
-};
-
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
- GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
-struct Templates50 {
- typedef TemplateSel<T1> Head;
- typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
- T43, T44, T45, T46, T47, T48, T49, T50> Tail;
-};
-
-
-// We don't want to require the users to write TemplatesN<...> directly,
-// as that would require them to count the length. Templates<...> is much
-// easier to write, but generates horrible messages when there is a
-// compiler error, as gcc insists on printing out each template
-// argument, even if it has the default value (this means Templates<list>
-// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
-// errors).
-//
-// Our solution is to combine the best part of the two approaches: a
-// user would write Templates<T1, ..., TN>, and Google Test will translate
-// that to TemplatesN<T1, ..., TN> internally to make error messages
-// readable. The translation is done by the 'type' member of the
-// Templates template.
-template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
- GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
- GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
- GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
- GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
- GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
- GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
- GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
- GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
- GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
- GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
- GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
- GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
- GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
- GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
- GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
- GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
- GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
- GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
- GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
- GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
- GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
- GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
- GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
- GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
-struct Templates {
- typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
-};
-
-template <>
-struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT> {
- typedef Templates0 type;
-};
-template <GTEST_TEMPLATE_ T1>
-struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT> {
- typedef Templates1<T1> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
-struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT> {
- typedef Templates2<T1, T2> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
-struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates3<T1, T2, T3> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4>
-struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates4<T1, T2, T3, T4> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
-struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates5<T1, T2, T3, T4, T5> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
-struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates6<T1, T2, T3, T4, T5, T6> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT> {
- typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT> {
- typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT> {
- typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT> {
- typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT> {
- typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT> {
- typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT> {
- typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT> {
- typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT> {
- typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT> {
- typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT> {
- typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT> {
- typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44, T45> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- T45, T46, NoneT, NoneT, NoneT, NoneT> {
- typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44, T45, T46> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- T45, T46, T47, NoneT, NoneT, NoneT> {
- typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44, T45, T46, T47> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- T45, T46, T47, T48, NoneT, NoneT> {
- typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44, T45, T46, T47, T48> type;
-};
-template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
- GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
- GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
- GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
- GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
- GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
- GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
- GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
- GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
- GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
- GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
- GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
- GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
- GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
- GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
- GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
- GTEST_TEMPLATE_ T49>
-struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
- T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
- T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
- T45, T46, T47, T48, T49, NoneT> {
- typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
- T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
- T42, T43, T44, T45, T46, T47, T48, T49> type;
-};
-
-// The TypeList template makes it possible to use either a single type
-// or a Types<...> list in TYPED_TEST_SUITE() and
-// INSTANTIATE_TYPED_TEST_SUITE_P().
-
-template <typename T>
-struct TypeList {
- typedef Types1<T> type;
-};
-
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7, typename T8, typename T9, typename T10,
- typename T11, typename T12, typename T13, typename T14, typename T15,
- typename T16, typename T17, typename T18, typename T19, typename T20,
- typename T21, typename T22, typename T23, typename T24, typename T25,
- typename T26, typename T27, typename T28, typename T29, typename T30,
- typename T31, typename T32, typename T33, typename T34, typename T35,
- typename T36, typename T37, typename T38, typename T39, typename T40,
- typename T41, typename T42, typename T43, typename T44, typename T45,
- typename T46, typename T47, typename T48, typename T49, typename T50>
-struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
- T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
- T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
- T44, T45, T46, T47, T48, T49, T50> > {
- typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
- T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
- T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
- T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
-};
-
-#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
-} // namespace internal
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+++ /dev/null
-$$ -*- mode: c++; -*-
-$var n = 50 $$ Maximum length of type lists we want to support.
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Type utilities needed for implementing typed and type-parameterized
-// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND!
-//
-// Currently we support at most $n types in a list, and at most $n
-// type-parameterized tests in one type-parameterized test suite.
-// Please contact googletestframework@googlegroups.com if you need
-// more.
-
-// GOOGLETEST_CM0001 DO NOT DELETE
-
-#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-
-#include "gtest/internal/gtest-port.h"
-
-// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
-// libstdc++ (which is where cxxabi.h comes from).
-# if GTEST_HAS_CXXABI_H_
-# include <cxxabi.h>
-# elif defined(__HP_aCC)
-# include <acxx_demangle.h>
-# endif // GTEST_HASH_CXXABI_H_
-
-namespace testing {
-namespace internal {
-
-// Canonicalizes a given name with respect to the Standard C++ Library.
-// This handles removing the inline namespace within `std` that is
-// used by various standard libraries (e.g., `std::__1`). Names outside
-// of namespace std are returned unmodified.
-inline std::string CanonicalizeForStdLibVersioning(std::string s) {
- static const char prefix[] = "std::__";
- if (s.compare(0, strlen(prefix), prefix) == 0) {
- std::string::size_type end = s.find("::", strlen(prefix));
- if (end != s.npos) {
- // Erase everything between the initial `std` and the second `::`.
- s.erase(strlen("std"), end - strlen("std"));
- }
- }
- return s;
-}
-
-// GetTypeName<T>() returns a human-readable name of type T.
-// NB: This function is also used in Google Mock, so don't move it inside of
-// the typed-test-only section below.
-template <typename T>
-std::string GetTypeName() {
-# if GTEST_HAS_RTTI
-
- const char* const name = typeid(T).name();
-# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
- int status = 0;
- // gcc's implementation of typeid(T).name() mangles the type name,
- // so we have to demangle it.
-# if GTEST_HAS_CXXABI_H_
- using abi::__cxa_demangle;
-# endif // GTEST_HAS_CXXABI_H_
- char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
- const std::string name_str(status == 0 ? readable_name : name);
- free(readable_name);
- return CanonicalizeForStdLibVersioning(name_str);
-# else
- return name;
-# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC
-
-# else
-
- return "<type>";
-
-# endif // GTEST_HAS_RTTI
-}
-
-#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
-// A unique type used as the default value for the arguments of class
-// template Types. This allows us to simulate variadic templates
-// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
-// support directly.
-struct None {};
-
-// The following family of struct and struct templates are used to
-// represent type lists. In particular, TypesN<T1, T2, ..., TN>
-// represents a type list with N types (T1, T2, ..., and TN) in it.
-// Except for Types0, every struct in the family has two member types:
-// Head for the first type in the list, and Tail for the rest of the
-// list.
-
-// The empty type list.
-struct Types0 {};
-
-// Type lists of length 1, 2, 3, and so on.
-
-template <typename T1>
-struct Types1 {
- typedef T1 Head;
- typedef Types0 Tail;
-};
-
-$range i 2..n
-
-$for i [[
-$range j 1..i
-$range k 2..i
-template <$for j, [[typename T$j]]>
-struct Types$i {
- typedef T1 Head;
- typedef Types$(i-1)<$for k, [[T$k]]> Tail;
-};
-
-
-]]
-
-} // namespace internal
-
-// We don't want to require the users to write TypesN<...> directly,
-// as that would require them to count the length. Types<...> is much
-// easier to write, but generates horrible messages when there is a
-// compiler error, as gcc insists on printing out each template
-// argument, even if it has the default value (this means Types<int>
-// will appear as Types<int, None, None, ..., None> in the compiler
-// errors).
-//
-// Our solution is to combine the best part of the two approaches: a
-// user would write Types<T1, ..., TN>, and Google Test will translate
-// that to TypesN<T1, ..., TN> internally to make error messages
-// readable. The translation is done by the 'type' member of the
-// Types template.
-
-$range i 1..n
-template <$for i, [[typename T$i = internal::None]]>
-struct Types {
- typedef internal::Types$n<$for i, [[T$i]]> type;
-};
-
-template <>
-struct Types<$for i, [[internal::None]]> {
- typedef internal::Types0 type;
-};
-
-$range i 1..n-1
-$for i [[
-$range j 1..i
-$range k i+1..n
-template <$for j, [[typename T$j]]>
-struct Types<$for j, [[T$j]]$for k[[, internal::None]]> {
- typedef internal::Types$i<$for j, [[T$j]]> type;
-};
-
-]]
-
-namespace internal {
-
-# define GTEST_TEMPLATE_ template <typename T> class
-
-// The template "selector" struct TemplateSel<Tmpl> is used to
-// represent Tmpl, which must be a class template with one type
-// parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined
-// as the type Tmpl<T>. This allows us to actually instantiate the
-// template "selected" by TemplateSel<Tmpl>.
-//
-// This trick is necessary for simulating typedef for class templates,
-// which C++ doesn't support directly.
-template <GTEST_TEMPLATE_ Tmpl>
-struct TemplateSel {
- template <typename T>
- struct Bind {
- typedef Tmpl<T> type;
- };
-};
-
-# define GTEST_BIND_(TmplSel, T) \
- TmplSel::template Bind<T>::type
-
-// A unique struct template used as the default value for the
-// arguments of class template Templates. This allows us to simulate
-// variadic templates (e.g. Templates<int>, Templates<int, double>,
-// and etc), which C++ doesn't support directly.
-template <typename T>
-struct NoneT {};
-
-// The following family of struct and struct templates are used to
-// represent template lists. In particular, TemplatesN<T1, T2, ...,
-// TN> represents a list of N templates (T1, T2, ..., and TN). Except
-// for Templates0, every struct in the family has two member types:
-// Head for the selector of the first template in the list, and Tail
-// for the rest of the list.
-
-// The empty template list.
-struct Templates0 {};
-
-// Template lists of length 1, 2, 3, and so on.
-
-template <GTEST_TEMPLATE_ T1>
-struct Templates1 {
- typedef TemplateSel<T1> Head;
- typedef Templates0 Tail;
-};
-
-$range i 2..n
-
-$for i [[
-$range j 1..i
-$range k 2..i
-template <$for j, [[GTEST_TEMPLATE_ T$j]]>
-struct Templates$i {
- typedef TemplateSel<T1> Head;
- typedef Templates$(i-1)<$for k, [[T$k]]> Tail;
-};
-
-
-]]
-
-// We don't want to require the users to write TemplatesN<...> directly,
-// as that would require them to count the length. Templates<...> is much
-// easier to write, but generates horrible messages when there is a
-// compiler error, as gcc insists on printing out each template
-// argument, even if it has the default value (this means Templates<list>
-// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
-// errors).
-//
-// Our solution is to combine the best part of the two approaches: a
-// user would write Templates<T1, ..., TN>, and Google Test will translate
-// that to TemplatesN<T1, ..., TN> internally to make error messages
-// readable. The translation is done by the 'type' member of the
-// Templates template.
-
-$range i 1..n
-template <$for i, [[GTEST_TEMPLATE_ T$i = NoneT]]>
-struct Templates {
- typedef Templates$n<$for i, [[T$i]]> type;
-};
-
-template <>
-struct Templates<$for i, [[NoneT]]> {
- typedef Templates0 type;
-};
-
-$range i 1..n-1
-$for i [[
-$range j 1..i
-$range k i+1..n
-template <$for j, [[GTEST_TEMPLATE_ T$j]]>
-struct Templates<$for j, [[T$j]]$for k[[, NoneT]]> {
- typedef Templates$i<$for j, [[T$j]]> type;
-};
-
-]]
-
-// The TypeList template makes it possible to use either a single type
-// or a Types<...> list in TYPED_TEST_SUITE() and
-// INSTANTIATE_TYPED_TEST_SUITE_P().
-
-template <typename T>
-struct TypeList {
- typedef Types1<T> type;
-};
-
-
-$range i 1..n
-template <$for i, [[typename T$i]]>
-struct TypeList<Types<$for i, [[T$i]]> > {
- typedef typename Types<$for i, [[T$i]]>::type type;
-};
-
-#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
-} // namespace internal
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
-// This provides interface PrimeTable that determines whether a number is a
-// prime and determines a next prime number. This interface is used
-// in Google Test samples demonstrating use of parameterized tests.
-
-#ifndef GTEST_SAMPLES_PRIME_TABLES_H_
-#define GTEST_SAMPLES_PRIME_TABLES_H_
-
-#include <algorithm>
-
-// The prime table interface.
-class PrimeTable {
- public:
- virtual ~PrimeTable() {}
-
- // Returns true if and only if n is a prime number.
- virtual bool IsPrime(int n) const = 0;
-
- // Returns the smallest prime number greater than p; or returns -1
- // if the next prime is beyond the capacity of the table.
- virtual int GetNextPrime(int p) const = 0;
-};
-
-// Implementation #1 calculates the primes on-the-fly.
-class OnTheFlyPrimeTable : public PrimeTable {
- public:
- bool IsPrime(int n) const override {
- if (n <= 1) return false;
-
- for (int i = 2; i*i <= n; i++) {
- // n is divisible by an integer other than 1 and itself.
- if ((n % i) == 0) return false;
- }
-
- return true;
- }
-
- int GetNextPrime(int p) const override {
- for (int n = p + 1; n > 0; n++) {
- if (IsPrime(n)) return n;
- }
-
- return -1;
- }
-};
-
-// Implementation #2 pre-calculates the primes and stores the result
-// in an array.
-class PreCalculatedPrimeTable : public PrimeTable {
- public:
- // 'max' specifies the maximum number the prime table holds.
- explicit PreCalculatedPrimeTable(int max)
- : is_prime_size_(max + 1), is_prime_(new bool[max + 1]) {
- CalculatePrimesUpTo(max);
- }
- ~PreCalculatedPrimeTable() override { delete[] is_prime_; }
-
- bool IsPrime(int n) const override {
- return 0 <= n && n < is_prime_size_ && is_prime_[n];
- }
-
- int GetNextPrime(int p) const override {
- for (int n = p + 1; n < is_prime_size_; n++) {
- if (is_prime_[n]) return n;
- }
-
- return -1;
- }
-
- private:
- void CalculatePrimesUpTo(int max) {
- ::std::fill(is_prime_, is_prime_ + is_prime_size_, true);
- is_prime_[0] = is_prime_[1] = false;
-
- // Checks every candidate for prime number (we know that 2 is the only even
- // prime).
- for (int i = 2; i*i <= max; i += i%2+1) {
- if (!is_prime_[i]) continue;
-
- // Marks all multiples of i (except i itself) as non-prime.
- // We are starting here from i-th multiplier, because all smaller
- // complex numbers were already marked.
- for (int j = i*i; j <= max; j += i) {
- is_prime_[j] = false;
- }
- }
- }
-
- const int is_prime_size_;
- bool* const is_prime_;
-
- // Disables compiler warning "assignment operator could not be generated."
- void operator=(const PreCalculatedPrimeTable& rhs);
-};
-
-#endif // GTEST_SAMPLES_PRIME_TABLES_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-#include "sample1.h"
-
-// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
-int Factorial(int n) {
- int result = 1;
- for (int i = 1; i <= n; i++) {
- result *= i;
- }
-
- return result;
-}
-
-// Returns true if and only if n is a prime number.
-bool IsPrime(int n) {
- // Trivial case 1: small numbers
- if (n <= 1) return false;
-
- // Trivial case 2: even numbers
- if (n % 2 == 0) return n == 2;
-
- // Now, we have that n is odd and n >= 3.
-
- // Try to divide n by every odd number i, starting from 3
- for (int i = 3; ; i += 2) {
- // We only have to try i up to the square root of n
- if (i > n/i) break;
-
- // Now, we have i <= n/i < n.
- // If n is divisible by i, n is not prime.
- if (n % i == 0) return false;
- }
-
- // n has no integer factor in the range (1, n), and thus is prime.
- return true;
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-#ifndef GTEST_SAMPLES_SAMPLE1_H_
-#define GTEST_SAMPLES_SAMPLE1_H_
-
-// Returns n! (the factorial of n). For negative n, n! is defined to be 1.
-int Factorial(int n);
-
-// Returns true if and only if n is a prime number.
-bool IsPrime(int n);
-
-#endif // GTEST_SAMPLES_SAMPLE1_H_
+++ /dev/null
-// Copyright 2009 Google Inc. All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This sample shows how to use Google Test listener API to implement
-// a primitive leak checker.
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "gtest/gtest.h"
-using ::testing::EmptyTestEventListener;
-using ::testing::InitGoogleTest;
-using ::testing::Test;
-using ::testing::TestEventListeners;
-using ::testing::TestInfo;
-using ::testing::TestPartResult;
-using ::testing::UnitTest;
-
-namespace {
-// We will track memory used by this class.
-class Water {
- public:
- // Normal Water declarations go here.
-
- // operator new and operator delete help us control water allocation.
- void* operator new(size_t allocation_size) {
- allocated_++;
- return malloc(allocation_size);
- }
-
- void operator delete(void* block, size_t /* allocation_size */) {
- allocated_--;
- free(block);
- }
-
- static int allocated() { return allocated_; }
-
- private:
- static int allocated_;
-};
-
-int Water::allocated_ = 0;
-
-// This event listener monitors how many Water objects are created and
-// destroyed by each test, and reports a failure if a test leaks some Water
-// objects. It does this by comparing the number of live Water objects at
-// the beginning of a test and at the end of a test.
-class LeakChecker : public EmptyTestEventListener {
- private:
- // Called before a test starts.
- void OnTestStart(const TestInfo& /* test_info */) override {
- initially_allocated_ = Water::allocated();
- }
-
- // Called after a test ends.
- void OnTestEnd(const TestInfo& /* test_info */) override {
- int difference = Water::allocated() - initially_allocated_;
-
- // You can generate a failure in any event handler except
- // OnTestPartResult. Just use an appropriate Google Test assertion to do
- // it.
- EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!";
- }
-
- int initially_allocated_;
-};
-
-TEST(ListenersTest, DoesNotLeak) {
- Water* water = new Water;
- delete water;
-}
-
-// This should fail when the --check_for_leaks command line flag is
-// specified.
-TEST(ListenersTest, LeaksWater) {
- Water* water = new Water;
- EXPECT_TRUE(water != nullptr);
-}
-} // namespace
-
-int main(int argc, char **argv) {
- InitGoogleTest(&argc, argv);
-
- bool check_for_leaks = false;
- if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0 )
- check_for_leaks = true;
- else
- printf("%s\n", "Run this program with --check_for_leaks to enable "
- "custom leak checking in the tests.");
-
- // If we are given the --check_for_leaks command line flag, installs the
- // leak checker.
- if (check_for_leaks) {
- TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
-
- // Adds the leak checker to the end of the test event listener list,
- // after the default text output printer and the default XML report
- // generator.
- //
- // The order is important - it ensures that failures generated in the
- // leak checker's OnTestEnd() method are processed by the text and XML
- // printers *before* their OnTestEnd() methods are called, such that
- // they are attributed to the right test. Remember that a listener
- // receives an OnXyzStart event *after* listeners preceding it in the
- // list received that event, and receives an OnXyzEnd event *before*
- // listeners preceding it.
- //
- // We don't need to worry about deleting the new listener later, as
- // Google Test will do it.
- listeners.Append(new LeakChecker);
- }
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-// This sample shows how to write a simple unit test for a function,
-// using Google C++ testing framework.
-//
-// Writing a unit test using Google C++ testing framework is easy as 1-2-3:
-
-
-// Step 1. Include necessary header files such that the stuff your
-// test logic needs is declared.
-//
-// Don't forget gtest.h, which declares the testing framework.
-
-#include <limits.h>
-#include "sample1.h"
-#include "gtest/gtest.h"
-namespace {
-
-// Step 2. Use the TEST macro to define your tests.
-//
-// TEST has two parameters: the test case name and the test name.
-// After using the macro, you should define your test logic between a
-// pair of braces. You can use a bunch of macros to indicate the
-// success or failure of a test. EXPECT_TRUE and EXPECT_EQ are
-// examples of such macros. For a complete list, see gtest.h.
-//
-// <TechnicalDetails>
-//
-// In Google Test, tests are grouped into test cases. This is how we
-// keep test code organized. You should put logically related tests
-// into the same test case.
-//
-// The test case name and the test name should both be valid C++
-// identifiers. And you should not use underscore (_) in the names.
-//
-// Google Test guarantees that each test you define is run exactly
-// once, but it makes no guarantee on the order the tests are
-// executed. Therefore, you should write your tests in such a way
-// that their results don't depend on their order.
-//
-// </TechnicalDetails>
-
-
-// Tests Factorial().
-
-// Tests factorial of negative numbers.
-TEST(FactorialTest, Negative) {
- // This test is named "Negative", and belongs to the "FactorialTest"
- // test case.
- EXPECT_EQ(1, Factorial(-5));
- EXPECT_EQ(1, Factorial(-1));
- EXPECT_GT(Factorial(-10), 0);
-
- // <TechnicalDetails>
- //
- // EXPECT_EQ(expected, actual) is the same as
- //
- // EXPECT_TRUE((expected) == (actual))
- //
- // except that it will print both the expected value and the actual
- // value when the assertion fails. This is very helpful for
- // debugging. Therefore in this case EXPECT_EQ is preferred.
- //
- // On the other hand, EXPECT_TRUE accepts any Boolean expression,
- // and is thus more general.
- //
- // </TechnicalDetails>
-}
-
-// Tests factorial of 0.
-TEST(FactorialTest, Zero) {
- EXPECT_EQ(1, Factorial(0));
-}
-
-// Tests factorial of positive numbers.
-TEST(FactorialTest, Positive) {
- EXPECT_EQ(1, Factorial(1));
- EXPECT_EQ(2, Factorial(2));
- EXPECT_EQ(6, Factorial(3));
- EXPECT_EQ(40320, Factorial(8));
-}
-
-
-// Tests IsPrime()
-
-// Tests negative input.
-TEST(IsPrimeTest, Negative) {
- // This test belongs to the IsPrimeTest test case.
-
- EXPECT_FALSE(IsPrime(-1));
- EXPECT_FALSE(IsPrime(-2));
- EXPECT_FALSE(IsPrime(INT_MIN));
-}
-
-// Tests some trivial cases.
-TEST(IsPrimeTest, Trivial) {
- EXPECT_FALSE(IsPrime(0));
- EXPECT_FALSE(IsPrime(1));
- EXPECT_TRUE(IsPrime(2));
- EXPECT_TRUE(IsPrime(3));
-}
-
-// Tests positive input.
-TEST(IsPrimeTest, Positive) {
- EXPECT_FALSE(IsPrime(4));
- EXPECT_TRUE(IsPrime(5));
- EXPECT_FALSE(IsPrime(6));
- EXPECT_TRUE(IsPrime(23));
-}
-} // namespace
-
-// Step 3. Call RUN_ALL_TESTS() in main().
-//
-// We do this by linking in src/gtest_main.cc file, which consists of
-// a main() function which calls RUN_ALL_TESTS() for us.
-//
-// This runs all the tests you've defined, prints the result, and
-// returns 0 if successful, or 1 otherwise.
-//
-// Did you notice that we didn't register the tests? The
-// RUN_ALL_TESTS() macro magically knows about all the tests we
-// defined. Isn't this convenient?
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-#include "sample2.h"
-
-#include <string.h>
-
-// Clones a 0-terminated C string, allocating memory using new.
-const char* MyString::CloneCString(const char* a_c_string) {
- if (a_c_string == nullptr) return nullptr;
-
- const size_t len = strlen(a_c_string);
- char* const clone = new char[ len + 1 ];
- memcpy(clone, a_c_string, len + 1);
-
- return clone;
-}
-
-// Sets the 0-terminated C string this MyString object
-// represents.
-void MyString::Set(const char* a_c_string) {
- // Makes sure this works when c_string == c_string_
- const char* const temp = MyString::CloneCString(a_c_string);
- delete[] c_string_;
- c_string_ = temp;
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-#ifndef GTEST_SAMPLES_SAMPLE2_H_
-#define GTEST_SAMPLES_SAMPLE2_H_
-
-#include <string.h>
-
-
-// A simple string class.
-class MyString {
- private:
- const char* c_string_;
- const MyString& operator=(const MyString& rhs);
-
- public:
- // Clones a 0-terminated C string, allocating memory using new.
- static const char* CloneCString(const char* a_c_string);
-
- ////////////////////////////////////////////////////////////
- //
- // C'tors
-
- // The default c'tor constructs a NULL string.
- MyString() : c_string_(nullptr) {}
-
- // Constructs a MyString by cloning a 0-terminated C string.
- explicit MyString(const char* a_c_string) : c_string_(nullptr) {
- Set(a_c_string);
- }
-
- // Copy c'tor
- MyString(const MyString& string) : c_string_(nullptr) {
- Set(string.c_string_);
- }
-
- ////////////////////////////////////////////////////////////
- //
- // D'tor. MyString is intended to be a final class, so the d'tor
- // doesn't need to be virtual.
- ~MyString() { delete[] c_string_; }
-
- // Gets the 0-terminated C string this MyString object represents.
- const char* c_string() const { return c_string_; }
-
- size_t Length() const { return c_string_ == nullptr ? 0 : strlen(c_string_); }
-
- // Sets the 0-terminated C string this MyString object represents.
- void Set(const char* c_string);
-};
-
-
-#endif // GTEST_SAMPLES_SAMPLE2_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-// This sample shows how to write a more complex unit test for a class
-// that has multiple member functions.
-//
-// Usually, it's a good idea to have one test for each method in your
-// class. You don't have to do that exactly, but it helps to keep
-// your tests organized. You may also throw in additional tests as
-// needed.
-
-#include "sample2.h"
-#include "gtest/gtest.h"
-namespace {
-// In this example, we test the MyString class (a simple string).
-
-// Tests the default c'tor.
-TEST(MyString, DefaultConstructor) {
- const MyString s;
-
- // Asserts that s.c_string() returns NULL.
- //
- // <TechnicalDetails>
- //
- // If we write NULL instead of
- //
- // static_cast<const char *>(NULL)
- //
- // in this assertion, it will generate a warning on gcc 3.4. The
- // reason is that EXPECT_EQ needs to know the types of its
- // arguments in order to print them when it fails. Since NULL is
- // #defined as 0, the compiler will use the formatter function for
- // int to print it. However, gcc thinks that NULL should be used as
- // a pointer, not an int, and therefore complains.
- //
- // The root of the problem is C++'s lack of distinction between the
- // integer number 0 and the null pointer constant. Unfortunately,
- // we have to live with this fact.
- //
- // </TechnicalDetails>
- EXPECT_STREQ(nullptr, s.c_string());
-
- EXPECT_EQ(0u, s.Length());
-}
-
-const char kHelloString[] = "Hello, world!";
-
-// Tests the c'tor that accepts a C string.
-TEST(MyString, ConstructorFromCString) {
- const MyString s(kHelloString);
- EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
- EXPECT_EQ(sizeof(kHelloString)/sizeof(kHelloString[0]) - 1,
- s.Length());
-}
-
-// Tests the copy c'tor.
-TEST(MyString, CopyConstructor) {
- const MyString s1(kHelloString);
- const MyString s2 = s1;
- EXPECT_EQ(0, strcmp(s2.c_string(), kHelloString));
-}
-
-// Tests the Set method.
-TEST(MyString, Set) {
- MyString s;
-
- s.Set(kHelloString);
- EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
-
- // Set should work when the input pointer is the same as the one
- // already in the MyString object.
- s.Set(s.c_string());
- EXPECT_EQ(0, strcmp(s.c_string(), kHelloString));
-
- // Can we set the MyString to NULL?
- s.Set(nullptr);
- EXPECT_STREQ(nullptr, s.c_string());
-}
-} // namespace
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-#ifndef GTEST_SAMPLES_SAMPLE3_INL_H_
-#define GTEST_SAMPLES_SAMPLE3_INL_H_
-
-#include <stddef.h>
-
-
-// Queue is a simple queue implemented as a singled-linked list.
-//
-// The element type must support copy constructor.
-template <typename E> // E is the element type
-class Queue;
-
-// QueueNode is a node in a Queue, which consists of an element of
-// type E and a pointer to the next node.
-template <typename E> // E is the element type
-class QueueNode {
- friend class Queue<E>;
-
- public:
- // Gets the element in this node.
- const E& element() const { return element_; }
-
- // Gets the next node in the queue.
- QueueNode* next() { return next_; }
- const QueueNode* next() const { return next_; }
-
- private:
- // Creates a node with a given element value. The next pointer is
- // set to NULL.
- explicit QueueNode(const E& an_element)
- : element_(an_element), next_(nullptr) {}
-
- // We disable the default assignment operator and copy c'tor.
- const QueueNode& operator = (const QueueNode&);
- QueueNode(const QueueNode&);
-
- E element_;
- QueueNode* next_;
-};
-
-template <typename E> // E is the element type.
-class Queue {
- public:
- // Creates an empty queue.
- Queue() : head_(nullptr), last_(nullptr), size_(0) {}
-
- // D'tor. Clears the queue.
- ~Queue() { Clear(); }
-
- // Clears the queue.
- void Clear() {
- if (size_ > 0) {
- // 1. Deletes every node.
- QueueNode<E>* node = head_;
- QueueNode<E>* next = node->next();
- for (; ;) {
- delete node;
- node = next;
- if (node == nullptr) break;
- next = node->next();
- }
-
- // 2. Resets the member variables.
- head_ = last_ = nullptr;
- size_ = 0;
- }
- }
-
- // Gets the number of elements.
- size_t Size() const { return size_; }
-
- // Gets the first element of the queue, or NULL if the queue is empty.
- QueueNode<E>* Head() { return head_; }
- const QueueNode<E>* Head() const { return head_; }
-
- // Gets the last element of the queue, or NULL if the queue is empty.
- QueueNode<E>* Last() { return last_; }
- const QueueNode<E>* Last() const { return last_; }
-
- // Adds an element to the end of the queue. A copy of the element is
- // created using the copy constructor, and then stored in the queue.
- // Changes made to the element in the queue doesn't affect the source
- // object, and vice versa.
- void Enqueue(const E& element) {
- QueueNode<E>* new_node = new QueueNode<E>(element);
-
- if (size_ == 0) {
- head_ = last_ = new_node;
- size_ = 1;
- } else {
- last_->next_ = new_node;
- last_ = new_node;
- size_++;
- }
- }
-
- // Removes the head of the queue and returns it. Returns NULL if
- // the queue is empty.
- E* Dequeue() {
- if (size_ == 0) {
- return nullptr;
- }
-
- const QueueNode<E>* const old_head = head_;
- head_ = head_->next_;
- size_--;
- if (size_ == 0) {
- last_ = nullptr;
- }
-
- E* element = new E(old_head->element());
- delete old_head;
-
- return element;
- }
-
- // Applies a function/functor on each element of the queue, and
- // returns the result in a new queue. The original queue is not
- // affected.
- template <typename F>
- Queue* Map(F function) const {
- Queue* new_queue = new Queue();
- for (const QueueNode<E>* node = head_; node != nullptr;
- node = node->next_) {
- new_queue->Enqueue(function(node->element()));
- }
-
- return new_queue;
- }
-
- private:
- QueueNode<E>* head_; // The first node of the queue.
- QueueNode<E>* last_; // The last node of the queue.
- size_t size_; // The number of elements in the queue.
-
- // We disallow copying a queue.
- Queue(const Queue&);
- const Queue& operator = (const Queue&);
-};
-
-#endif // GTEST_SAMPLES_SAMPLE3_INL_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-// In this example, we use a more advanced feature of Google Test called
-// test fixture.
-//
-// A test fixture is a place to hold objects and functions shared by
-// all tests in a test case. Using a test fixture avoids duplicating
-// the test code necessary to initialize and cleanup those common
-// objects for each test. It is also useful for defining sub-routines
-// that your tests need to invoke a lot.
-//
-// <TechnicalDetails>
-//
-// The tests share the test fixture in the sense of code sharing, not
-// data sharing. Each test is given its own fresh copy of the
-// fixture. You cannot expect the data modified by one test to be
-// passed on to another test, which is a bad idea.
-//
-// The reason for this design is that tests should be independent and
-// repeatable. In particular, a test should not fail as the result of
-// another test's failure. If one test depends on info produced by
-// another test, then the two tests should really be one big test.
-//
-// The macros for indicating the success/failure of a test
-// (EXPECT_TRUE, FAIL, etc) need to know what the current test is
-// (when Google Test prints the test result, it tells you which test
-// each failure belongs to). Technically, these macros invoke a
-// member function of the Test class. Therefore, you cannot use them
-// in a global function. That's why you should put test sub-routines
-// in a test fixture.
-//
-// </TechnicalDetails>
-
-#include "sample3-inl.h"
-#include "gtest/gtest.h"
-namespace {
-// To use a test fixture, derive a class from testing::Test.
-class QueueTestSmpl3 : public testing::Test {
- protected: // You should make the members protected s.t. they can be
- // accessed from sub-classes.
-
- // virtual void SetUp() will be called before each test is run. You
- // should define it if you need to initialize the variables.
- // Otherwise, this can be skipped.
- void SetUp() override {
- q1_.Enqueue(1);
- q2_.Enqueue(2);
- q2_.Enqueue(3);
- }
-
- // virtual void TearDown() will be called after each test is run.
- // You should define it if there is cleanup work to do. Otherwise,
- // you don't have to provide it.
- //
- // virtual void TearDown() {
- // }
-
- // A helper function that some test uses.
- static int Double(int n) {
- return 2*n;
- }
-
- // A helper function for testing Queue::Map().
- void MapTester(const Queue<int> * q) {
- // Creates a new queue, where each element is twice as big as the
- // corresponding one in q.
- const Queue<int> * const new_q = q->Map(Double);
-
- // Verifies that the new queue has the same size as q.
- ASSERT_EQ(q->Size(), new_q->Size());
-
- // Verifies the relationship between the elements of the two queues.
- for (const QueueNode<int>*n1 = q->Head(), *n2 = new_q->Head();
- n1 != nullptr; n1 = n1->next(), n2 = n2->next()) {
- EXPECT_EQ(2 * n1->element(), n2->element());
- }
-
- delete new_q;
- }
-
- // Declares the variables your tests want to use.
- Queue<int> q0_;
- Queue<int> q1_;
- Queue<int> q2_;
-};
-
-// When you have a test fixture, you define a test using TEST_F
-// instead of TEST.
-
-// Tests the default c'tor.
-TEST_F(QueueTestSmpl3, DefaultConstructor) {
- // You can access data in the test fixture here.
- EXPECT_EQ(0u, q0_.Size());
-}
-
-// Tests Dequeue().
-TEST_F(QueueTestSmpl3, Dequeue) {
- int * n = q0_.Dequeue();
- EXPECT_TRUE(n == nullptr);
-
- n = q1_.Dequeue();
- ASSERT_TRUE(n != nullptr);
- EXPECT_EQ(1, *n);
- EXPECT_EQ(0u, q1_.Size());
- delete n;
-
- n = q2_.Dequeue();
- ASSERT_TRUE(n != nullptr);
- EXPECT_EQ(2, *n);
- EXPECT_EQ(1u, q2_.Size());
- delete n;
-}
-
-// Tests the Queue::Map() function.
-TEST_F(QueueTestSmpl3, Map) {
- MapTester(&q0_);
- MapTester(&q1_);
- MapTester(&q2_);
-}
-} // namespace
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-
-#include <stdio.h>
-
-#include "sample4.h"
-
-// Returns the current counter value, and increments it.
-int Counter::Increment() {
- return counter_++;
-}
-
-// Returns the current counter value, and decrements it.
-// counter can not be less than 0, return 0 in this case
-int Counter::Decrement() {
- if (counter_ == 0) {
- return counter_;
- } else {
- return counter_--;
- }
-}
-
-// Prints the current counter value to STDOUT.
-void Counter::Print() const {
- printf("%d", counter_);
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// A sample program demonstrating using Google C++ testing framework.
-#ifndef GTEST_SAMPLES_SAMPLE4_H_
-#define GTEST_SAMPLES_SAMPLE4_H_
-
-// A simple monotonic counter.
-class Counter {
- private:
- int counter_;
-
- public:
- // Creates a counter that starts at 0.
- Counter() : counter_(0) {}
-
- // Returns the current counter value, and increments it.
- int Increment();
-
- // Returns the current counter value, and decrements it.
- int Decrement();
-
- // Prints the current counter value to STDOUT.
- void Print() const;
-};
-
-#endif // GTEST_SAMPLES_SAMPLE4_H_
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "sample4.h"
-#include "gtest/gtest.h"
-
-namespace {
-// Tests the Increment() method.
-
-TEST(Counter, Increment) {
- Counter c;
-
- // Test that counter 0 returns 0
- EXPECT_EQ(0, c.Decrement());
-
- // EXPECT_EQ() evaluates its arguments exactly once, so they
- // can have side effects.
-
- EXPECT_EQ(0, c.Increment());
- EXPECT_EQ(1, c.Increment());
- EXPECT_EQ(2, c.Increment());
-
- EXPECT_EQ(3, c.Decrement());
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This sample teaches how to reuse a test fixture in multiple test
-// cases by deriving sub-fixtures from it.
-//
-// When you define a test fixture, you specify the name of the test
-// case that will use this fixture. Therefore, a test fixture can
-// be used by only one test case.
-//
-// Sometimes, more than one test cases may want to use the same or
-// slightly different test fixtures. For example, you may want to
-// make sure that all tests for a GUI library don't leak important
-// system resources like fonts and brushes. In Google Test, you do
-// this by putting the shared logic in a super (as in "super class")
-// test fixture, and then have each test case use a fixture derived
-// from this super fixture.
-
-#include <limits.h>
-#include <time.h>
-#include "gtest/gtest.h"
-#include "sample1.h"
-#include "sample3-inl.h"
-namespace {
-// In this sample, we want to ensure that every test finishes within
-// ~5 seconds. If a test takes longer to run, we consider it a
-// failure.
-//
-// We put the code for timing a test in a test fixture called
-// "QuickTest". QuickTest is intended to be the super fixture that
-// other fixtures derive from, therefore there is no test case with
-// the name "QuickTest". This is OK.
-//
-// Later, we will derive multiple test fixtures from QuickTest.
-class QuickTest : public testing::Test {
- protected:
- // Remember that SetUp() is run immediately before a test starts.
- // This is a good place to record the start time.
- void SetUp() override { start_time_ = time(nullptr); }
-
- // TearDown() is invoked immediately after a test finishes. Here we
- // check if the test was too slow.
- void TearDown() override {
- // Gets the time when the test finishes
- const time_t end_time = time(nullptr);
-
- // Asserts that the test took no more than ~5 seconds. Did you
- // know that you can use assertions in SetUp() and TearDown() as
- // well?
- EXPECT_TRUE(end_time - start_time_ <= 5) << "The test took too long.";
- }
-
- // The UTC time (in seconds) when the test starts
- time_t start_time_;
-};
-
-
-// We derive a fixture named IntegerFunctionTest from the QuickTest
-// fixture. All tests using this fixture will be automatically
-// required to be quick.
-class IntegerFunctionTest : public QuickTest {
- // We don't need any more logic than already in the QuickTest fixture.
- // Therefore the body is empty.
-};
-
-
-// Now we can write tests in the IntegerFunctionTest test case.
-
-// Tests Factorial()
-TEST_F(IntegerFunctionTest, Factorial) {
- // Tests factorial of negative numbers.
- EXPECT_EQ(1, Factorial(-5));
- EXPECT_EQ(1, Factorial(-1));
- EXPECT_GT(Factorial(-10), 0);
-
- // Tests factorial of 0.
- EXPECT_EQ(1, Factorial(0));
-
- // Tests factorial of positive numbers.
- EXPECT_EQ(1, Factorial(1));
- EXPECT_EQ(2, Factorial(2));
- EXPECT_EQ(6, Factorial(3));
- EXPECT_EQ(40320, Factorial(8));
-}
-
-
-// Tests IsPrime()
-TEST_F(IntegerFunctionTest, IsPrime) {
- // Tests negative input.
- EXPECT_FALSE(IsPrime(-1));
- EXPECT_FALSE(IsPrime(-2));
- EXPECT_FALSE(IsPrime(INT_MIN));
-
- // Tests some trivial cases.
- EXPECT_FALSE(IsPrime(0));
- EXPECT_FALSE(IsPrime(1));
- EXPECT_TRUE(IsPrime(2));
- EXPECT_TRUE(IsPrime(3));
-
- // Tests positive input.
- EXPECT_FALSE(IsPrime(4));
- EXPECT_TRUE(IsPrime(5));
- EXPECT_FALSE(IsPrime(6));
- EXPECT_TRUE(IsPrime(23));
-}
-
-
-// The next test case (named "QueueTest") also needs to be quick, so
-// we derive another fixture from QuickTest.
-//
-// The QueueTest test fixture has some logic and shared objects in
-// addition to what's in QuickTest already. We define the additional
-// stuff inside the body of the test fixture, as usual.
-class QueueTest : public QuickTest {
- protected:
- void SetUp() override {
- // First, we need to set up the super fixture (QuickTest).
- QuickTest::SetUp();
-
- // Second, some additional setup for this fixture.
- q1_.Enqueue(1);
- q2_.Enqueue(2);
- q2_.Enqueue(3);
- }
-
- // By default, TearDown() inherits the behavior of
- // QuickTest::TearDown(). As we have no additional cleaning work
- // for QueueTest, we omit it here.
- //
- // virtual void TearDown() {
- // QuickTest::TearDown();
- // }
-
- Queue<int> q0_;
- Queue<int> q1_;
- Queue<int> q2_;
-};
-
-
-// Now, let's write tests using the QueueTest fixture.
-
-// Tests the default constructor.
-TEST_F(QueueTest, DefaultConstructor) {
- EXPECT_EQ(0u, q0_.Size());
-}
-
-// Tests Dequeue().
-TEST_F(QueueTest, Dequeue) {
- int* n = q0_.Dequeue();
- EXPECT_TRUE(n == nullptr);
-
- n = q1_.Dequeue();
- EXPECT_TRUE(n != nullptr);
- EXPECT_EQ(1, *n);
- EXPECT_EQ(0u, q1_.Size());
- delete n;
-
- n = q2_.Dequeue();
- EXPECT_TRUE(n != nullptr);
- EXPECT_EQ(2, *n);
- EXPECT_EQ(1u, q2_.Size());
- delete n;
-}
-} // namespace
-// If necessary, you can derive further test fixtures from a derived
-// fixture itself. For example, you can derive another fixture from
-// QueueTest. Google Test imposes no limit on how deep the hierarchy
-// can be. In practice, however, you probably don't want it to be too
-// deep as to be confusing.
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This sample shows how to test common properties of multiple
-// implementations of the same interface (aka interface tests).
-
-// The interface and its implementations are in this header.
-#include "prime_tables.h"
-
-#include "gtest/gtest.h"
-namespace {
-// First, we define some factory functions for creating instances of
-// the implementations. You may be able to skip this step if all your
-// implementations can be constructed the same way.
-
-template <class T>
-PrimeTable* CreatePrimeTable();
-
-template <>
-PrimeTable* CreatePrimeTable<OnTheFlyPrimeTable>() {
- return new OnTheFlyPrimeTable;
-}
-
-template <>
-PrimeTable* CreatePrimeTable<PreCalculatedPrimeTable>() {
- return new PreCalculatedPrimeTable(10000);
-}
-
-// Then we define a test fixture class template.
-template <class T>
-class PrimeTableTest : public testing::Test {
- protected:
- // The ctor calls the factory function to create a prime table
- // implemented by T.
- PrimeTableTest() : table_(CreatePrimeTable<T>()) {}
-
- ~PrimeTableTest() override { delete table_; }
-
- // Note that we test an implementation via the base interface
- // instead of the actual implementation class. This is important
- // for keeping the tests close to the real world scenario, where the
- // implementation is invoked via the base interface. It avoids
- // got-yas where the implementation class has a method that shadows
- // a method with the same name (but slightly different argument
- // types) in the base interface, for example.
- PrimeTable* const table_;
-};
-
-#if GTEST_HAS_TYPED_TEST
-
-using testing::Types;
-
-// Google Test offers two ways for reusing tests for different types.
-// The first is called "typed tests". You should use it if you
-// already know *all* the types you are gonna exercise when you write
-// the tests.
-
-// To write a typed test case, first use
-//
-// TYPED_TEST_SUITE(TestCaseName, TypeList);
-//
-// to declare it and specify the type parameters. As with TEST_F,
-// TestCaseName must match the test fixture name.
-
-// The list of types we want to test.
-typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable> Implementations;
-
-TYPED_TEST_SUITE(PrimeTableTest, Implementations);
-
-// Then use TYPED_TEST(TestCaseName, TestName) to define a typed test,
-// similar to TEST_F.
-TYPED_TEST(PrimeTableTest, ReturnsFalseForNonPrimes) {
- // Inside the test body, you can refer to the type parameter by
- // TypeParam, and refer to the fixture class by TestFixture. We
- // don't need them in this example.
-
- // Since we are in the template world, C++ requires explicitly
- // writing 'this->' when referring to members of the fixture class.
- // This is something you have to learn to live with.
- EXPECT_FALSE(this->table_->IsPrime(-5));
- EXPECT_FALSE(this->table_->IsPrime(0));
- EXPECT_FALSE(this->table_->IsPrime(1));
- EXPECT_FALSE(this->table_->IsPrime(4));
- EXPECT_FALSE(this->table_->IsPrime(6));
- EXPECT_FALSE(this->table_->IsPrime(100));
-}
-
-TYPED_TEST(PrimeTableTest, ReturnsTrueForPrimes) {
- EXPECT_TRUE(this->table_->IsPrime(2));
- EXPECT_TRUE(this->table_->IsPrime(3));
- EXPECT_TRUE(this->table_->IsPrime(5));
- EXPECT_TRUE(this->table_->IsPrime(7));
- EXPECT_TRUE(this->table_->IsPrime(11));
- EXPECT_TRUE(this->table_->IsPrime(131));
-}
-
-TYPED_TEST(PrimeTableTest, CanGetNextPrime) {
- EXPECT_EQ(2, this->table_->GetNextPrime(0));
- EXPECT_EQ(3, this->table_->GetNextPrime(2));
- EXPECT_EQ(5, this->table_->GetNextPrime(3));
- EXPECT_EQ(7, this->table_->GetNextPrime(5));
- EXPECT_EQ(11, this->table_->GetNextPrime(7));
- EXPECT_EQ(131, this->table_->GetNextPrime(128));
-}
-
-// That's it! Google Test will repeat each TYPED_TEST for each type
-// in the type list specified in TYPED_TEST_SUITE. Sit back and be
-// happy that you don't have to define them multiple times.
-
-#endif // GTEST_HAS_TYPED_TEST
-
-#if GTEST_HAS_TYPED_TEST_P
-
-using testing::Types;
-
-// Sometimes, however, you don't yet know all the types that you want
-// to test when you write the tests. For example, if you are the
-// author of an interface and expect other people to implement it, you
-// might want to write a set of tests to make sure each implementation
-// conforms to some basic requirements, but you don't know what
-// implementations will be written in the future.
-//
-// How can you write the tests without committing to the type
-// parameters? That's what "type-parameterized tests" can do for you.
-// It is a bit more involved than typed tests, but in return you get a
-// test pattern that can be reused in many contexts, which is a big
-// win. Here's how you do it:
-
-// First, define a test fixture class template. Here we just reuse
-// the PrimeTableTest fixture defined earlier:
-
-template <class T>
-class PrimeTableTest2 : public PrimeTableTest<T> {
-};
-
-// Then, declare the test case. The argument is the name of the test
-// fixture, and also the name of the test case (as usual). The _P
-// suffix is for "parameterized" or "pattern".
-TYPED_TEST_SUITE_P(PrimeTableTest2);
-
-// Next, use TYPED_TEST_P(TestCaseName, TestName) to define a test,
-// similar to what you do with TEST_F.
-TYPED_TEST_P(PrimeTableTest2, ReturnsFalseForNonPrimes) {
- EXPECT_FALSE(this->table_->IsPrime(-5));
- EXPECT_FALSE(this->table_->IsPrime(0));
- EXPECT_FALSE(this->table_->IsPrime(1));
- EXPECT_FALSE(this->table_->IsPrime(4));
- EXPECT_FALSE(this->table_->IsPrime(6));
- EXPECT_FALSE(this->table_->IsPrime(100));
-}
-
-TYPED_TEST_P(PrimeTableTest2, ReturnsTrueForPrimes) {
- EXPECT_TRUE(this->table_->IsPrime(2));
- EXPECT_TRUE(this->table_->IsPrime(3));
- EXPECT_TRUE(this->table_->IsPrime(5));
- EXPECT_TRUE(this->table_->IsPrime(7));
- EXPECT_TRUE(this->table_->IsPrime(11));
- EXPECT_TRUE(this->table_->IsPrime(131));
-}
-
-TYPED_TEST_P(PrimeTableTest2, CanGetNextPrime) {
- EXPECT_EQ(2, this->table_->GetNextPrime(0));
- EXPECT_EQ(3, this->table_->GetNextPrime(2));
- EXPECT_EQ(5, this->table_->GetNextPrime(3));
- EXPECT_EQ(7, this->table_->GetNextPrime(5));
- EXPECT_EQ(11, this->table_->GetNextPrime(7));
- EXPECT_EQ(131, this->table_->GetNextPrime(128));
-}
-
-// Type-parameterized tests involve one extra step: you have to
-// enumerate the tests you defined:
-REGISTER_TYPED_TEST_SUITE_P(
- PrimeTableTest2, // The first argument is the test case name.
- // The rest of the arguments are the test names.
- ReturnsFalseForNonPrimes, ReturnsTrueForPrimes, CanGetNextPrime);
-
-// At this point the test pattern is done. However, you don't have
-// any real test yet as you haven't said which types you want to run
-// the tests with.
-
-// To turn the abstract test pattern into real tests, you instantiate
-// it with a list of types. Usually the test pattern will be defined
-// in a .h file, and anyone can #include and instantiate it. You can
-// even instantiate it more than once in the same program. To tell
-// different instances apart, you give each of them a name, which will
-// become part of the test case name and can be used in test filters.
-
-// The list of types we want to test. Note that it doesn't have to be
-// defined at the time we write the TYPED_TEST_P()s.
-typedef Types<OnTheFlyPrimeTable, PreCalculatedPrimeTable>
- PrimeTableImplementations;
-INSTANTIATE_TYPED_TEST_SUITE_P(OnTheFlyAndPreCalculated, // Instance name
- PrimeTableTest2, // Test case name
- PrimeTableImplementations); // Type list
-
-#endif // GTEST_HAS_TYPED_TEST_P
-} // namespace
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This sample shows how to test common properties of multiple
-// implementations of an interface (aka interface tests) using
-// value-parameterized tests. Each test in the test case has
-// a parameter that is an interface pointer to an implementation
-// tested.
-
-// The interface and its implementations are in this header.
-#include "prime_tables.h"
-
-#include "gtest/gtest.h"
-namespace {
-
-using ::testing::TestWithParam;
-using ::testing::Values;
-
-// As a general rule, to prevent a test from affecting the tests that come
-// after it, you should create and destroy the tested objects for each test
-// instead of reusing them. In this sample we will define a simple factory
-// function for PrimeTable objects. We will instantiate objects in test's
-// SetUp() method and delete them in TearDown() method.
-typedef PrimeTable* CreatePrimeTableFunc();
-
-PrimeTable* CreateOnTheFlyPrimeTable() {
- return new OnTheFlyPrimeTable();
-}
-
-template <size_t max_precalculated>
-PrimeTable* CreatePreCalculatedPrimeTable() {
- return new PreCalculatedPrimeTable(max_precalculated);
-}
-
-// Inside the test body, fixture constructor, SetUp(), and TearDown() you
-// can refer to the test parameter by GetParam(). In this case, the test
-// parameter is a factory function which we call in fixture's SetUp() to
-// create and store an instance of PrimeTable.
-class PrimeTableTestSmpl7 : public TestWithParam<CreatePrimeTableFunc*> {
- public:
- ~PrimeTableTestSmpl7() override { delete table_; }
- void SetUp() override { table_ = (*GetParam())(); }
- void TearDown() override {
- delete table_;
- table_ = nullptr;
- }
-
- protected:
- PrimeTable* table_;
-};
-
-TEST_P(PrimeTableTestSmpl7, ReturnsFalseForNonPrimes) {
- EXPECT_FALSE(table_->IsPrime(-5));
- EXPECT_FALSE(table_->IsPrime(0));
- EXPECT_FALSE(table_->IsPrime(1));
- EXPECT_FALSE(table_->IsPrime(4));
- EXPECT_FALSE(table_->IsPrime(6));
- EXPECT_FALSE(table_->IsPrime(100));
-}
-
-TEST_P(PrimeTableTestSmpl7, ReturnsTrueForPrimes) {
- EXPECT_TRUE(table_->IsPrime(2));
- EXPECT_TRUE(table_->IsPrime(3));
- EXPECT_TRUE(table_->IsPrime(5));
- EXPECT_TRUE(table_->IsPrime(7));
- EXPECT_TRUE(table_->IsPrime(11));
- EXPECT_TRUE(table_->IsPrime(131));
-}
-
-TEST_P(PrimeTableTestSmpl7, CanGetNextPrime) {
- EXPECT_EQ(2, table_->GetNextPrime(0));
- EXPECT_EQ(3, table_->GetNextPrime(2));
- EXPECT_EQ(5, table_->GetNextPrime(3));
- EXPECT_EQ(7, table_->GetNextPrime(5));
- EXPECT_EQ(11, table_->GetNextPrime(7));
- EXPECT_EQ(131, table_->GetNextPrime(128));
-}
-
-// In order to run value-parameterized tests, you need to instantiate them,
-// or bind them to a list of values which will be used as test parameters.
-// You can instantiate them in a different translation module, or even
-// instantiate them several times.
-//
-// Here, we instantiate our tests with a list of two PrimeTable object
-// factory functions:
-INSTANTIATE_TEST_SUITE_P(OnTheFlyAndPreCalculated, PrimeTableTestSmpl7,
- Values(&CreateOnTheFlyPrimeTable,
- &CreatePreCalculatedPrimeTable<1000>));
-
-} // namespace
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This sample shows how to test code relying on some global flag variables.
-// Combine() helps with generating all possible combinations of such flags,
-// and each test is given one combination as a parameter.
-
-// Use class definitions to test from this header.
-#include "prime_tables.h"
-
-#include "gtest/gtest.h"
-namespace {
-
-// Suppose we want to introduce a new, improved implementation of PrimeTable
-// which combines speed of PrecalcPrimeTable and versatility of
-// OnTheFlyPrimeTable (see prime_tables.h). Inside it instantiates both
-// PrecalcPrimeTable and OnTheFlyPrimeTable and uses the one that is more
-// appropriate under the circumstances. But in low memory conditions, it can be
-// told to instantiate without PrecalcPrimeTable instance at all and use only
-// OnTheFlyPrimeTable.
-class HybridPrimeTable : public PrimeTable {
- public:
- HybridPrimeTable(bool force_on_the_fly, int max_precalculated)
- : on_the_fly_impl_(new OnTheFlyPrimeTable),
- precalc_impl_(force_on_the_fly
- ? nullptr
- : new PreCalculatedPrimeTable(max_precalculated)),
- max_precalculated_(max_precalculated) {}
- ~HybridPrimeTable() override {
- delete on_the_fly_impl_;
- delete precalc_impl_;
- }
-
- bool IsPrime(int n) const override {
- if (precalc_impl_ != nullptr && n < max_precalculated_)
- return precalc_impl_->IsPrime(n);
- else
- return on_the_fly_impl_->IsPrime(n);
- }
-
- int GetNextPrime(int p) const override {
- int next_prime = -1;
- if (precalc_impl_ != nullptr && p < max_precalculated_)
- next_prime = precalc_impl_->GetNextPrime(p);
-
- return next_prime != -1 ? next_prime : on_the_fly_impl_->GetNextPrime(p);
- }
-
- private:
- OnTheFlyPrimeTable* on_the_fly_impl_;
- PreCalculatedPrimeTable* precalc_impl_;
- int max_precalculated_;
-};
-
-using ::testing::TestWithParam;
-using ::testing::Bool;
-using ::testing::Values;
-using ::testing::Combine;
-
-// To test all code paths for HybridPrimeTable we must test it with numbers
-// both within and outside PreCalculatedPrimeTable's capacity and also with
-// PreCalculatedPrimeTable disabled. We do this by defining fixture which will
-// accept different combinations of parameters for instantiating a
-// HybridPrimeTable instance.
-class PrimeTableTest : public TestWithParam< ::std::tuple<bool, int> > {
- protected:
- void SetUp() override {
- bool force_on_the_fly;
- int max_precalculated;
- std::tie(force_on_the_fly, max_precalculated) = GetParam();
- table_ = new HybridPrimeTable(force_on_the_fly, max_precalculated);
- }
- void TearDown() override {
- delete table_;
- table_ = nullptr;
- }
- HybridPrimeTable* table_;
-};
-
-TEST_P(PrimeTableTest, ReturnsFalseForNonPrimes) {
- // Inside the test body, you can refer to the test parameter by GetParam().
- // In this case, the test parameter is a PrimeTable interface pointer which
- // we can use directly.
- // Please note that you can also save it in the fixture's SetUp() method
- // or constructor and use saved copy in the tests.
-
- EXPECT_FALSE(table_->IsPrime(-5));
- EXPECT_FALSE(table_->IsPrime(0));
- EXPECT_FALSE(table_->IsPrime(1));
- EXPECT_FALSE(table_->IsPrime(4));
- EXPECT_FALSE(table_->IsPrime(6));
- EXPECT_FALSE(table_->IsPrime(100));
-}
-
-TEST_P(PrimeTableTest, ReturnsTrueForPrimes) {
- EXPECT_TRUE(table_->IsPrime(2));
- EXPECT_TRUE(table_->IsPrime(3));
- EXPECT_TRUE(table_->IsPrime(5));
- EXPECT_TRUE(table_->IsPrime(7));
- EXPECT_TRUE(table_->IsPrime(11));
- EXPECT_TRUE(table_->IsPrime(131));
-}
-
-TEST_P(PrimeTableTest, CanGetNextPrime) {
- EXPECT_EQ(2, table_->GetNextPrime(0));
- EXPECT_EQ(3, table_->GetNextPrime(2));
- EXPECT_EQ(5, table_->GetNextPrime(3));
- EXPECT_EQ(7, table_->GetNextPrime(5));
- EXPECT_EQ(11, table_->GetNextPrime(7));
- EXPECT_EQ(131, table_->GetNextPrime(128));
-}
-
-// In order to run value-parameterized tests, you need to instantiate them,
-// or bind them to a list of values which will be used as test parameters.
-// You can instantiate them in a different translation module, or even
-// instantiate them several times.
-//
-// Here, we instantiate our tests with a list of parameters. We must combine
-// all variations of the boolean flag suppressing PrecalcPrimeTable and some
-// meaningful values for tests. We choose a small value (1), and a value that
-// will put some of the tested numbers beyond the capability of the
-// PrecalcPrimeTable instance and some inside it (10). Combine will produce all
-// possible combinations.
-INSTANTIATE_TEST_SUITE_P(MeaningfulTestParameters, PrimeTableTest,
- Combine(Bool(), Values(1, 10)));
-
-} // namespace
+++ /dev/null
-// Copyright 2009 Google Inc. All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This sample shows how to use Google Test listener API to implement
-// an alternative console output and how to use the UnitTest reflection API
-// to enumerate test cases and tests and to inspect their results.
-
-#include <stdio.h>
-
-#include "gtest/gtest.h"
-
-using ::testing::EmptyTestEventListener;
-using ::testing::InitGoogleTest;
-using ::testing::Test;
-using ::testing::TestCase;
-using ::testing::TestEventListeners;
-using ::testing::TestInfo;
-using ::testing::TestPartResult;
-using ::testing::UnitTest;
-namespace {
-// Provides alternative output mode which produces minimal amount of
-// information about tests.
-class TersePrinter : public EmptyTestEventListener {
- private:
- // Called before any test activity starts.
- void OnTestProgramStart(const UnitTest& /* unit_test */) override {}
-
- // Called after all test activities have ended.
- void OnTestProgramEnd(const UnitTest& unit_test) override {
- fprintf(stdout, "TEST %s\n", unit_test.Passed() ? "PASSED" : "FAILED");
- fflush(stdout);
- }
-
- // Called before a test starts.
- void OnTestStart(const TestInfo& test_info) override {
- fprintf(stdout,
- "*** Test %s.%s starting.\n",
- test_info.test_case_name(),
- test_info.name());
- fflush(stdout);
- }
-
- // Called after a failed assertion or a SUCCEED() invocation.
- void OnTestPartResult(const TestPartResult& test_part_result) override {
- fprintf(stdout,
- "%s in %s:%d\n%s\n",
- test_part_result.failed() ? "*** Failure" : "Success",
- test_part_result.file_name(),
- test_part_result.line_number(),
- test_part_result.summary());
- fflush(stdout);
- }
-
- // Called after a test ends.
- void OnTestEnd(const TestInfo& test_info) override {
- fprintf(stdout,
- "*** Test %s.%s ending.\n",
- test_info.test_case_name(),
- test_info.name());
- fflush(stdout);
- }
-}; // class TersePrinter
-
-TEST(CustomOutputTest, PrintsMessage) {
- printf("Printing something from the test body...\n");
-}
-
-TEST(CustomOutputTest, Succeeds) {
- SUCCEED() << "SUCCEED() has been invoked from here";
-}
-
-TEST(CustomOutputTest, Fails) {
- EXPECT_EQ(1, 2)
- << "This test fails in order to demonstrate alternative failure messages";
-}
-} // namespace
-
-int main(int argc, char **argv) {
- InitGoogleTest(&argc, argv);
-
- bool terse_output = false;
- if (argc > 1 && strcmp(argv[1], "--terse_output") == 0 )
- terse_output = true;
- else
- printf("%s\n", "Run this program with --terse_output to change the way "
- "it prints its output.");
-
- UnitTest& unit_test = *UnitTest::GetInstance();
-
- // If we are given the --terse_output command line flag, suppresses the
- // standard output and attaches own result printer.
- if (terse_output) {
- TestEventListeners& listeners = unit_test.listeners();
-
- // Removes the default console output listener from the list so it will
- // not receive events from Google Test and won't print any output. Since
- // this operation transfers ownership of the listener to the caller we
- // have to delete it as well.
- delete listeners.Release(listeners.default_result_printer());
-
- // Adds the custom output listener to the list. It will now receive
- // events from Google Test and print the alternative output. We don't
- // have to worry about deleting it since Google Test assumes ownership
- // over it after adding it to the list.
- listeners.Append(new TersePrinter);
- }
- int ret_val = RUN_ALL_TESTS();
-
- // This is an example of using the UnitTest reflection API to inspect test
- // results. Here we discount failures from the tests we expected to fail.
- int unexpectedly_failed_tests = 0;
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
- const testing::TestSuite& test_suite = *unit_test.GetTestSuite(i);
- for (int j = 0; j < test_suite.total_test_count(); ++j) {
- const TestInfo& test_info = *test_suite.GetTestInfo(j);
- // Counts failed tests that were not meant to fail (those without
- // 'Fails' in the name).
- if (test_info.result()->Failed() &&
- strcmp(test_info.name(), "Fails") != 0) {
- unexpectedly_failed_tests++;
- }
- }
- }
-
- // Test that were meant to fail should not affect the test program outcome.
- if (unexpectedly_failed_tests == 0)
- ret_val = 0;
-
- return ret_val;
-}
+++ /dev/null
-# Copyright 2013 Google Inc. All Rights Reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Shared utilities for writing scripts for Google Test/Mock."""
-
-__author__ = 'wan@google.com (Zhanyong Wan)'
-
-
-import os
-import re
-
-
-# Matches the line from 'svn info .' output that describes what SVN
-# path the current local directory corresponds to. For example, in
-# a googletest SVN workspace's trunk/test directory, the output will be:
-#
-# URL: https://googletest.googlecode.com/svn/trunk/test
-_SVN_INFO_URL_RE = re.compile(r'^URL: https://(\w+)\.googlecode\.com/svn(.*)')
-
-
-def GetCommandOutput(command):
- """Runs the shell command and returns its stdout as a list of lines."""
-
- f = os.popen(command, 'r')
- lines = [line.strip() for line in f.readlines()]
- f.close()
- return lines
-
-
-def GetSvnInfo():
- """Returns the project name and the current SVN workspace's root path."""
-
- for line in GetCommandOutput('svn info .'):
- m = _SVN_INFO_URL_RE.match(line)
- if m:
- project = m.group(1) # googletest or googlemock
- rel_path = m.group(2)
- root = os.path.realpath(rel_path.count('/') * '../')
- return project, root
-
- return None, None
-
-
-def GetSvnTrunk():
- """Returns the current SVN workspace's trunk root path."""
-
- _, root = GetSvnInfo()
- return root + '/trunk' if root else None
-
-
-def IsInGTestSvn():
- project, _ = GetSvnInfo()
- return project == 'googletest'
-
-
-def IsInGMockSvn():
- project, _ = GetSvnInfo()
- return project == 'googlemock'
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""fuse_gtest_files.py v0.2.0
-Fuses Google Test source code into a .h file and a .cc file.
-
-SYNOPSIS
- fuse_gtest_files.py [GTEST_ROOT_DIR] OUTPUT_DIR
-
- Scans GTEST_ROOT_DIR for Google Test source code, and generates
- two files: OUTPUT_DIR/gtest/gtest.h and OUTPUT_DIR/gtest/gtest-all.cc.
- Then you can build your tests by adding OUTPUT_DIR to the include
- search path and linking with OUTPUT_DIR/gtest/gtest-all.cc. These
- two files contain everything you need to use Google Test. Hence
- you can "install" Google Test by copying them to wherever you want.
-
- GTEST_ROOT_DIR can be omitted and defaults to the parent
- directory of the directory holding this script.
-
-EXAMPLES
- ./fuse_gtest_files.py fused_gtest
- ./fuse_gtest_files.py path/to/unpacked/gtest fused_gtest
-
-This tool is experimental. In particular, it assumes that there is no
-conditional inclusion of Google Test headers. Please report any
-problems to googletestframework@googlegroups.com. You can read
-https://github.com/google/googletest/blob/master/googletest/docs/advanced.md for
-more information.
-"""
-
-__author__ = 'wan@google.com (Zhanyong Wan)'
-
-import os
-import re
-try:
- from sets import Set as set # For Python 2.3 compatibility
-except ImportError:
- pass
-import sys
-
-# We assume that this file is in the scripts/ directory in the Google
-# Test root directory.
-DEFAULT_GTEST_ROOT_DIR = os.path.join(os.path.dirname(__file__), '..')
-
-# Regex for matching '#include "gtest/..."'.
-INCLUDE_GTEST_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(gtest/.+)"')
-
-# Regex for matching '#include "src/..."'.
-INCLUDE_SRC_FILE_REGEX = re.compile(r'^\s*#\s*include\s*"(src/.+)"')
-
-# Where to find the source seed files.
-GTEST_H_SEED = 'include/gtest/gtest.h'
-GTEST_SPI_H_SEED = 'include/gtest/gtest-spi.h'
-GTEST_ALL_CC_SEED = 'src/gtest-all.cc'
-
-# Where to put the generated files.
-GTEST_H_OUTPUT = 'gtest/gtest.h'
-GTEST_ALL_CC_OUTPUT = 'gtest/gtest-all.cc'
-
-
-def VerifyFileExists(directory, relative_path):
- """Verifies that the given file exists; aborts on failure.
-
- relative_path is the file path relative to the given directory.
- """
-
- if not os.path.isfile(os.path.join(directory, relative_path)):
- print('ERROR: Cannot find %s in directory %s.' % (relative_path,
- directory))
- print('Please either specify a valid project root directory '
- 'or omit it on the command line.')
- sys.exit(1)
-
-
-def ValidateGTestRootDir(gtest_root):
- """Makes sure gtest_root points to a valid gtest root directory.
-
- The function aborts the program on failure.
- """
-
- VerifyFileExists(gtest_root, GTEST_H_SEED)
- VerifyFileExists(gtest_root, GTEST_ALL_CC_SEED)
-
-
-def VerifyOutputFile(output_dir, relative_path):
- """Verifies that the given output file path is valid.
-
- relative_path is relative to the output_dir directory.
- """
-
- # Makes sure the output file either doesn't exist or can be overwritten.
- output_file = os.path.join(output_dir, relative_path)
- if os.path.exists(output_file):
- # TODO(wan@google.com): The following user-interaction doesn't
- # work with automated processes. We should provide a way for the
- # Makefile to force overwriting the files.
- print('%s already exists in directory %s - overwrite it? (y/N) ' %
- (relative_path, output_dir))
- answer = sys.stdin.readline().strip()
- if answer not in ['y', 'Y']:
- print('ABORTED.')
- sys.exit(1)
-
- # Makes sure the directory holding the output file exists; creates
- # it and all its ancestors if necessary.
- parent_directory = os.path.dirname(output_file)
- if not os.path.isdir(parent_directory):
- os.makedirs(parent_directory)
-
-
-def ValidateOutputDir(output_dir):
- """Makes sure output_dir points to a valid output directory.
-
- The function aborts the program on failure.
- """
-
- VerifyOutputFile(output_dir, GTEST_H_OUTPUT)
- VerifyOutputFile(output_dir, GTEST_ALL_CC_OUTPUT)
-
-
-def FuseGTestH(gtest_root, output_dir):
- """Scans folder gtest_root to generate gtest/gtest.h in output_dir."""
-
- output_file = open(os.path.join(output_dir, GTEST_H_OUTPUT), 'w')
- processed_files = set() # Holds all gtest headers we've processed.
-
- def ProcessFile(gtest_header_path):
- """Processes the given gtest header file."""
-
- # We don't process the same header twice.
- if gtest_header_path in processed_files:
- return
-
- processed_files.add(gtest_header_path)
-
- # Reads each line in the given gtest header.
- for line in open(os.path.join(gtest_root, gtest_header_path), 'r'):
- m = INCLUDE_GTEST_FILE_REGEX.match(line)
- if m:
- # It's '#include "gtest/..."' - let's process it recursively.
- ProcessFile('include/' + m.group(1))
- else:
- # Otherwise we copy the line unchanged to the output file.
- output_file.write(line)
-
- ProcessFile(GTEST_H_SEED)
- output_file.close()
-
-
-def FuseGTestAllCcToFile(gtest_root, output_file):
- """Scans folder gtest_root to generate gtest/gtest-all.cc in output_file."""
-
- processed_files = set()
-
- def ProcessFile(gtest_source_file):
- """Processes the given gtest source file."""
-
- # We don't process the same #included file twice.
- if gtest_source_file in processed_files:
- return
-
- processed_files.add(gtest_source_file)
-
- # Reads each line in the given gtest source file.
- for line in open(os.path.join(gtest_root, gtest_source_file), 'r'):
- m = INCLUDE_GTEST_FILE_REGEX.match(line)
- if m:
- if 'include/' + m.group(1) == GTEST_SPI_H_SEED:
- # It's '#include "gtest/gtest-spi.h"'. This file is not
- # #included by "gtest/gtest.h", so we need to process it.
- ProcessFile(GTEST_SPI_H_SEED)
- else:
- # It's '#include "gtest/foo.h"' where foo is not gtest-spi.
- # We treat it as '#include "gtest/gtest.h"', as all other
- # gtest headers are being fused into gtest.h and cannot be
- # #included directly.
-
- # There is no need to #include "gtest/gtest.h" more than once.
- if not GTEST_H_SEED in processed_files:
- processed_files.add(GTEST_H_SEED)
- output_file.write('#include "%s"\n' % (GTEST_H_OUTPUT,))
- else:
- m = INCLUDE_SRC_FILE_REGEX.match(line)
- if m:
- # It's '#include "src/foo"' - let's process it recursively.
- ProcessFile(m.group(1))
- else:
- output_file.write(line)
-
- ProcessFile(GTEST_ALL_CC_SEED)
-
-
-def FuseGTestAllCc(gtest_root, output_dir):
- """Scans folder gtest_root to generate gtest/gtest-all.cc in output_dir."""
-
- output_file = open(os.path.join(output_dir, GTEST_ALL_CC_OUTPUT), 'w')
- FuseGTestAllCcToFile(gtest_root, output_file)
- output_file.close()
-
-
-def FuseGTest(gtest_root, output_dir):
- """Fuses gtest.h and gtest-all.cc."""
-
- ValidateGTestRootDir(gtest_root)
- ValidateOutputDir(output_dir)
-
- FuseGTestH(gtest_root, output_dir)
- FuseGTestAllCc(gtest_root, output_dir)
-
-
-def main():
- argc = len(sys.argv)
- if argc == 2:
- # fuse_gtest_files.py OUTPUT_DIR
- FuseGTest(DEFAULT_GTEST_ROOT_DIR, sys.argv[1])
- elif argc == 3:
- # fuse_gtest_files.py GTEST_ROOT_DIR OUTPUT_DIR
- FuseGTest(sys.argv[1], sys.argv[2])
- else:
- print(__doc__)
- sys.exit(1)
-
-
-if __name__ == '__main__':
- main()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""gen_gtest_pred_impl.py v0.1
-
-Generates the implementation of Google Test predicate assertions and
-accompanying tests.
-
-Usage:
-
- gen_gtest_pred_impl.py MAX_ARITY
-
-where MAX_ARITY is a positive integer.
-
-The command generates the implementation of up-to MAX_ARITY-ary
-predicate assertions, and writes it to file gtest_pred_impl.h in the
-directory where the script is. It also generates the accompanying
-unit test in file gtest_pred_impl_unittest.cc.
-"""
-
-__author__ = 'wan@google.com (Zhanyong Wan)'
-
-import os
-import sys
-import time
-
-# Where this script is.
-SCRIPT_DIR = os.path.dirname(sys.argv[0])
-
-# Where to store the generated header.
-HEADER = os.path.join(SCRIPT_DIR, '../include/gtest/gtest_pred_impl.h')
-
-# Where to store the generated unit test.
-UNIT_TEST = os.path.join(SCRIPT_DIR, '../test/gtest_pred_impl_unittest.cc')
-
-
-def HeaderPreamble(n):
- """Returns the preamble for the header file.
-
- Args:
- n: the maximum arity of the predicate macros to be generated.
- """
-
- # A map that defines the values used in the preamble template.
- DEFS = {
- 'today' : time.strftime('%m/%d/%Y'),
- 'year' : time.strftime('%Y'),
- 'command' : '%s %s' % (os.path.basename(sys.argv[0]), n),
- 'n' : n
- }
-
- return (
-"""// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file is AUTOMATICALLY GENERATED on %(today)s by command
-// '%(command)s'. DO NOT EDIT BY HAND!
-//
-// Implements a family of generic predicate assertion macros.
-
-#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
-#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
-
-#include "gtest/gtest.h"
-
-namespace testing {
-
-// This header implements a family of generic predicate assertion
-// macros:
-//
-// ASSERT_PRED_FORMAT1(pred_format, v1)
-// ASSERT_PRED_FORMAT2(pred_format, v1, v2)
-// ...
-//
-// where pred_format is a function or functor that takes n (in the
-// case of ASSERT_PRED_FORMATn) values and their source expression
-// text, and returns a testing::AssertionResult. See the definition
-// of ASSERT_EQ in gtest.h for an example.
-//
-// If you don't care about formatting, you can use the more
-// restrictive version:
-//
-// ASSERT_PRED1(pred, v1)
-// ASSERT_PRED2(pred, v1, v2)
-// ...
-//
-// where pred is an n-ary function or functor that returns bool,
-// and the values v1, v2, ..., must support the << operator for
-// streaming to std::ostream.
-//
-// We also define the EXPECT_* variations.
-//
-// For now we only support predicates whose arity is at most %(n)s.
-// Please email googletestframework@googlegroups.com if you need
-// support for higher arities.
-
-// GTEST_ASSERT_ is the basic statement to which all of the assertions
-// in this file reduce. Don't use this in your code.
-
-#define GTEST_ASSERT_(expression, on_failure) \\
- GTEST_AMBIGUOUS_ELSE_BLOCKER_ \\
- if (const ::testing::AssertionResult gtest_ar = (expression)) \\
- ; \\
- else \\
- on_failure(gtest_ar.failure_message())
-""" % DEFS)
-
-
-def Arity(n):
- """Returns the English name of the given arity."""
-
- if n < 0:
- return None
- elif n <= 3:
- return ['nullary', 'unary', 'binary', 'ternary'][n]
- else:
- return '%s-ary' % n
-
-
-def Title(word):
- """Returns the given word in title case. The difference between
- this and string's title() method is that Title('4-ary') is '4-ary'
- while '4-ary'.title() is '4-Ary'."""
-
- return word[0].upper() + word[1:]
-
-
-def OneTo(n):
- """Returns the list [1, 2, 3, ..., n]."""
-
- return range(1, n + 1)
-
-
-def Iter(n, format, sep=''):
- """Given a positive integer n, a format string that contains 0 or
- more '%s' format specs, and optionally a separator string, returns
- the join of n strings, each formatted with the format string on an
- iterator ranged from 1 to n.
-
- Example:
-
- Iter(3, 'v%s', sep=', ') returns 'v1, v2, v3'.
- """
-
- # How many '%s' specs are in format?
- spec_count = len(format.split('%s')) - 1
- return sep.join([format % (spec_count * (i,)) for i in OneTo(n)])
-
-
-def ImplementationForArity(n):
- """Returns the implementation of n-ary predicate assertions."""
-
- # A map the defines the values used in the implementation template.
- DEFS = {
- 'n' : str(n),
- 'vs' : Iter(n, 'v%s', sep=', '),
- 'vts' : Iter(n, '#v%s', sep=', '),
- 'arity' : Arity(n),
- 'Arity' : Title(Arity(n))
- }
-
- impl = """
-
-// Helper function for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use
-// this in your code.
-template <typename Pred""" % DEFS
-
- impl += Iter(n, """,
- typename T%s""")
-
- impl += """>
-AssertionResult AssertPred%(n)sHelper(const char* pred_text""" % DEFS
-
- impl += Iter(n, """,
- const char* e%s""")
-
- impl += """,
- Pred pred"""
-
- impl += Iter(n, """,
- const T%s& v%s""")
-
- impl += """) {
- if (pred(%(vs)s)) return AssertionSuccess();
-
-""" % DEFS
-
- impl += ' return AssertionFailure() << pred_text << "("'
-
- impl += Iter(n, """
- << e%s""", sep=' << ", "')
-
- impl += ' << ") evaluates to false, where"'
-
- impl += Iter(n, """
- << "\\n" << e%s << " evaluates to " << v%s""")
-
- impl += """;
-}
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
-// Don't use this in your code.
-#define GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, on_failure)\\
- GTEST_ASSERT_(pred_format(%(vts)s, %(vs)s), \\
- on_failure)
-
-// Internal macro for implementing {EXPECT|ASSERT}_PRED%(n)s. Don't use
-// this in your code.
-#define GTEST_PRED%(n)s_(pred, %(vs)s, on_failure)\\
- GTEST_ASSERT_(::testing::AssertPred%(n)sHelper(#pred""" % DEFS
-
- impl += Iter(n, """, \\
- #v%s""")
-
- impl += """, \\
- pred"""
-
- impl += Iter(n, """, \\
- v%s""")
-
- impl += """), on_failure)
-
-// %(Arity)s predicate assertion macros.
-#define EXPECT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
- GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_NONFATAL_FAILURE_)
-#define EXPECT_PRED%(n)s(pred, %(vs)s) \\
- GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_NONFATAL_FAILURE_)
-#define ASSERT_PRED_FORMAT%(n)s(pred_format, %(vs)s) \\
- GTEST_PRED_FORMAT%(n)s_(pred_format, %(vs)s, GTEST_FATAL_FAILURE_)
-#define ASSERT_PRED%(n)s(pred, %(vs)s) \\
- GTEST_PRED%(n)s_(pred, %(vs)s, GTEST_FATAL_FAILURE_)
-
-""" % DEFS
-
- return impl
-
-
-def HeaderPostamble():
- """Returns the postamble for the header file."""
-
- return """
-
-} // namespace testing
-
-#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
-"""
-
-
-def GenerateFile(path, content):
- """Given a file path and a content string
- overwrites it with the given content.
- """
- print 'Updating file %s . . .' % path
- f = file(path, 'w+')
- print >>f, content,
- f.close()
-
- print 'File %s has been updated.' % path
-
-
-def GenerateHeader(n):
- """Given the maximum arity n, updates the header file that implements
- the predicate assertions.
- """
- GenerateFile(HEADER,
- HeaderPreamble(n)
- + ''.join([ImplementationForArity(i) for i in OneTo(n)])
- + HeaderPostamble())
-
-
-def UnitTestPreamble():
- """Returns the preamble for the unit test file."""
-
- # A map that defines the values used in the preamble template.
- DEFS = {
- 'today' : time.strftime('%m/%d/%Y'),
- 'year' : time.strftime('%Y'),
- 'command' : '%s %s' % (os.path.basename(sys.argv[0]), sys.argv[1]),
- }
-
- return (
-"""// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file is AUTOMATICALLY GENERATED on %(today)s by command
-// '%(command)s'. DO NOT EDIT BY HAND!
-
-// Regression test for gtest_pred_impl.h
-//
-// This file is generated by a script and quite long. If you intend to
-// learn how Google Test works by reading its unit tests, read
-// gtest_unittest.cc instead.
-//
-// This is intended as a regression test for the Google Test predicate
-// assertions. We compile it as part of the gtest_unittest target
-// only to keep the implementation tidy and compact, as it is quite
-// involved to set up the stage for testing Google Test using Google
-// Test itself.
-//
-// Currently, gtest_unittest takes ~11 seconds to run in the testing
-// daemon. In the future, if it grows too large and needs much more
-// time to finish, we should consider separating this file into a
-// stand-alone regression test.
-
-#include <iostream>
-
-#include "gtest/gtest.h"
-#include "gtest/gtest-spi.h"
-
-// A user-defined data type.
-struct Bool {
- explicit Bool(int val) : value(val != 0) {}
-
- bool operator>(int n) const { return value > Bool(n).value; }
-
- Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
-
- bool operator==(const Bool& rhs) const { return value == rhs.value; }
-
- bool value;
-};
-
-// Enables Bool to be used in assertions.
-std::ostream& operator<<(std::ostream& os, const Bool& x) {
- return os << (x.value ? "true" : "false");
-}
-
-""" % DEFS)
-
-
-def TestsForArity(n):
- """Returns the tests for n-ary predicate assertions."""
-
- # A map that defines the values used in the template for the tests.
- DEFS = {
- 'n' : n,
- 'es' : Iter(n, 'e%s', sep=', '),
- 'vs' : Iter(n, 'v%s', sep=', '),
- 'vts' : Iter(n, '#v%s', sep=', '),
- 'tvs' : Iter(n, 'T%s v%s', sep=', '),
- 'int_vs' : Iter(n, 'int v%s', sep=', '),
- 'Bool_vs' : Iter(n, 'Bool v%s', sep=', '),
- 'types' : Iter(n, 'typename T%s', sep=', '),
- 'v_sum' : Iter(n, 'v%s', sep=' + '),
- 'arity' : Arity(n),
- 'Arity' : Title(Arity(n)),
- }
-
- tests = (
-"""// Sample functions/functors for testing %(arity)s predicate assertions.
-
-// A %(arity)s predicate function.
-template <%(types)s>
-bool PredFunction%(n)s(%(tvs)s) {
- return %(v_sum)s > 0;
-}
-
-// The following two functions are needed to circumvent a bug in
-// gcc 2.95.3, which sometimes has problem with the above template
-// function.
-bool PredFunction%(n)sInt(%(int_vs)s) {
- return %(v_sum)s > 0;
-}
-bool PredFunction%(n)sBool(%(Bool_vs)s) {
- return %(v_sum)s > 0;
-}
-""" % DEFS)
-
- tests += """
-// A %(arity)s predicate functor.
-struct PredFunctor%(n)s {
- template <%(types)s>
- bool operator()(""" % DEFS
-
- tests += Iter(n, 'const T%s& v%s', sep=""",
- """)
-
- tests += """) {
- return %(v_sum)s > 0;
- }
-};
-""" % DEFS
-
- tests += """
-// A %(arity)s predicate-formatter function.
-template <%(types)s>
-testing::AssertionResult PredFormatFunction%(n)s(""" % DEFS
-
- tests += Iter(n, 'const char* e%s', sep=""",
- """)
-
- tests += Iter(n, """,
- const T%s& v%s""")
-
- tests += """) {
- if (PredFunction%(n)s(%(vs)s))
- return testing::AssertionSuccess();
-
- return testing::AssertionFailure()
- << """ % DEFS
-
- tests += Iter(n, 'e%s', sep=' << " + " << ')
-
- tests += """
- << " is expected to be positive, but evaluates to "
- << %(v_sum)s << ".";
-}
-""" % DEFS
-
- tests += """
-// A %(arity)s predicate-formatter functor.
-struct PredFormatFunctor%(n)s {
- template <%(types)s>
- testing::AssertionResult operator()(""" % DEFS
-
- tests += Iter(n, 'const char* e%s', sep=""",
- """)
-
- tests += Iter(n, """,
- const T%s& v%s""")
-
- tests += """) const {
- return PredFormatFunction%(n)s(%(es)s, %(vs)s);
- }
-};
-""" % DEFS
-
- tests += """
-// Tests for {EXPECT|ASSERT}_PRED_FORMAT%(n)s.
-
-class Predicate%(n)sTest : public testing::Test {
- protected:
- virtual void SetUp() {
- expected_to_finish_ = true;
- finished_ = false;""" % DEFS
-
- tests += """
- """ + Iter(n, 'n%s_ = ') + """0;
- }
-"""
-
- tests += """
- virtual void TearDown() {
- // Verifies that each of the predicate's arguments was evaluated
- // exactly once."""
-
- tests += ''.join(["""
- EXPECT_EQ(1, n%s_) <<
- "The predicate assertion didn't evaluate argument %s "
- "exactly once.";""" % (i, i + 1) for i in OneTo(n)])
-
- tests += """
-
- // Verifies that the control flow in the test function is expected.
- if (expected_to_finish_ && !finished_) {
- FAIL() << "The predicate assertion unexpactedly aborted the test.";
- } else if (!expected_to_finish_ && finished_) {
- FAIL() << "The failed predicate assertion didn't abort the test "
- "as expected.";
- }
- }
-
- // true iff the test function is expected to run to finish.
- static bool expected_to_finish_;
-
- // true iff the test function did run to finish.
- static bool finished_;
-""" % DEFS
-
- tests += Iter(n, """
- static int n%s_;""")
-
- tests += """
-};
-
-bool Predicate%(n)sTest::expected_to_finish_;
-bool Predicate%(n)sTest::finished_;
-""" % DEFS
-
- tests += Iter(n, """int Predicate%%(n)sTest::n%s_;
-""") % DEFS
-
- tests += """
-typedef Predicate%(n)sTest EXPECT_PRED_FORMAT%(n)sTest;
-typedef Predicate%(n)sTest ASSERT_PRED_FORMAT%(n)sTest;
-typedef Predicate%(n)sTest EXPECT_PRED%(n)sTest;
-typedef Predicate%(n)sTest ASSERT_PRED%(n)sTest;
-""" % DEFS
-
- def GenTest(use_format, use_assert, expect_failure,
- use_functor, use_user_type):
- """Returns the test for a predicate assertion macro.
-
- Args:
- use_format: true iff the assertion is a *_PRED_FORMAT*.
- use_assert: true iff the assertion is a ASSERT_*.
- expect_failure: true iff the assertion is expected to fail.
- use_functor: true iff the first argument of the assertion is
- a functor (as opposed to a function)
- use_user_type: true iff the predicate functor/function takes
- argument(s) of a user-defined type.
-
- Example:
-
- GenTest(1, 0, 0, 1, 0) returns a test that tests the behavior
- of a successful EXPECT_PRED_FORMATn() that takes a functor
- whose arguments have built-in types."""
-
- if use_assert:
- assrt = 'ASSERT' # 'assert' is reserved, so we cannot use
- # that identifier here.
- else:
- assrt = 'EXPECT'
-
- assertion = assrt + '_PRED'
-
- if use_format:
- pred_format = 'PredFormat'
- assertion += '_FORMAT'
- else:
- pred_format = 'Pred'
-
- assertion += '%(n)s' % DEFS
-
- if use_functor:
- pred_format_type = 'functor'
- pred_format += 'Functor%(n)s()'
- else:
- pred_format_type = 'function'
- pred_format += 'Function%(n)s'
- if not use_format:
- if use_user_type:
- pred_format += 'Bool'
- else:
- pred_format += 'Int'
-
- test_name = pred_format_type.title()
-
- if use_user_type:
- arg_type = 'user-defined type (Bool)'
- test_name += 'OnUserType'
- if expect_failure:
- arg = 'Bool(n%s_++)'
- else:
- arg = 'Bool(++n%s_)'
- else:
- arg_type = 'built-in type (int)'
- test_name += 'OnBuiltInType'
- if expect_failure:
- arg = 'n%s_++'
- else:
- arg = '++n%s_'
-
- if expect_failure:
- successful_or_failed = 'failed'
- expected_or_not = 'expected.'
- test_name += 'Failure'
- else:
- successful_or_failed = 'successful'
- expected_or_not = 'UNEXPECTED!'
- test_name += 'Success'
-
- # A map that defines the values used in the test template.
- defs = DEFS.copy()
- defs.update({
- 'assert' : assrt,
- 'assertion' : assertion,
- 'test_name' : test_name,
- 'pf_type' : pred_format_type,
- 'pf' : pred_format,
- 'arg_type' : arg_type,
- 'arg' : arg,
- 'successful' : successful_or_failed,
- 'expected' : expected_or_not,
- })
-
- test = """
-// Tests a %(successful)s %(assertion)s where the
-// predicate-formatter is a %(pf_type)s on a %(arg_type)s.
-TEST_F(%(assertion)sTest, %(test_name)s) {""" % defs
-
- indent = (len(assertion) + 3)*' '
- extra_indent = ''
-
- if expect_failure:
- extra_indent = ' '
- if use_assert:
- test += """
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT"""
- else:
- test += """
- EXPECT_NONFATAL_FAILURE({ // NOLINT"""
-
- test += '\n' + extra_indent + """ %(assertion)s(%(pf)s""" % defs
-
- test = test % defs
- test += Iter(n, ',\n' + indent + extra_indent + '%(arg)s' % defs)
- test += ');\n' + extra_indent + ' finished_ = true;\n'
-
- if expect_failure:
- test += ' }, "");\n'
-
- test += '}\n'
- return test
-
- # Generates tests for all 2**6 = 64 combinations.
- tests += ''.join([GenTest(use_format, use_assert, expect_failure,
- use_functor, use_user_type)
- for use_format in [0, 1]
- for use_assert in [0, 1]
- for expect_failure in [0, 1]
- for use_functor in [0, 1]
- for use_user_type in [0, 1]
- ])
-
- return tests
-
-
-def UnitTestPostamble():
- """Returns the postamble for the tests."""
-
- return ''
-
-
-def GenerateUnitTest(n):
- """Returns the tests for up-to n-ary predicate assertions."""
-
- GenerateFile(UNIT_TEST,
- UnitTestPreamble()
- + ''.join([TestsForArity(i) for i in OneTo(n)])
- + UnitTestPostamble())
-
-
-def _Main():
- """The entry point of the script. Generates the header file and its
- unit test."""
-
- if len(sys.argv) != 2:
- print __doc__
- print 'Author: ' + __author__
- sys.exit(1)
-
- n = int(sys.argv[1])
- GenerateHeader(n)
- GenerateUnitTest(n)
-
-
-if __name__ == '__main__':
- _Main()
+++ /dev/null
-#!/bin/sh
-
-# These variables are automatically filled in by the configure script.
-name="@PACKAGE_TARNAME@"
-version="@PACKAGE_VERSION@"
-
-show_usage()
-{
- echo "Usage: gtest-config [OPTIONS...]"
-}
-
-show_help()
-{
- show_usage
- cat <<\EOF
-
-The `gtest-config' script provides access to the necessary compile and linking
-flags to connect with Google C++ Testing Framework, both in a build prior to
-installation, and on the system proper after installation. The installation
-overrides may be issued in combination with any other queries, but will only
-affect installation queries if called on a built but not installed gtest. The
-installation queries may not be issued with any other types of queries, and
-only one installation query may be made at a time. The version queries and
-compiler flag queries may be combined as desired but not mixed. Different
-version queries are always combined with logical "and" semantics, and only the
-last of any particular query is used while all previous ones ignored. All
-versions must be specified as a sequence of numbers separated by periods.
-Compiler flag queries output the union of the sets of flags when combined.
-
- Examples:
- gtest-config --min-version=1.0 || echo "Insufficient Google Test version."
-
- g++ $(gtest-config --cppflags --cxxflags) -o foo.o -c foo.cpp
- g++ $(gtest-config --ldflags --libs) -o foo foo.o
-
- # When using a built but not installed Google Test:
- g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
-
- # When using an installed Google Test, but with installation overrides:
- export GTEST_PREFIX="/opt"
- g++ $(gtest-config --libdir="/opt/lib64" ...) ...
-
- Help:
- --usage brief usage information
- --help display this help message
-
- Installation Overrides:
- --prefix=<dir> overrides the installation prefix
- --exec-prefix=<dir> overrides the executable installation prefix
- --libdir=<dir> overrides the library installation prefix
- --includedir=<dir> overrides the header file installation prefix
-
- Installation Queries:
- --prefix installation prefix
- --exec-prefix executable installation prefix
- --libdir library installation directory
- --includedir header file installation directory
- --version the version of the Google Test installation
-
- Version Queries:
- --min-version=VERSION return 0 if the version is at least VERSION
- --exact-version=VERSION return 0 if the version is exactly VERSION
- --max-version=VERSION return 0 if the version is at most VERSION
-
- Compilation Flag Queries:
- --cppflags compile flags specific to the C-like preprocessors
- --cxxflags compile flags appropriate for C++ programs
- --ldflags linker flags
- --libs libraries for linking
-
-EOF
-}
-
-# This function bounds our version with a min and a max. It uses some clever
-# POSIX-compliant variable expansion to portably do all the work in the shell
-# and avoid any dependency on a particular "sed" or "awk" implementation.
-# Notable is that it will only ever compare the first 3 components of versions.
-# Further components will be cleanly stripped off. All versions must be
-# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and
-# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should
-# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than
-# continuing to maintain our own shell version.
-check_versions()
-{
- major_version=${version%%.*}
- minor_version="0"
- point_version="0"
- if test "${version#*.}" != "${version}"; then
- minor_version=${version#*.}
- minor_version=${minor_version%%.*}
- fi
- if test "${version#*.*.}" != "${version}"; then
- point_version=${version#*.*.}
- point_version=${point_version%%.*}
- fi
-
- min_version="$1"
- min_major_version=${min_version%%.*}
- min_minor_version="0"
- min_point_version="0"
- if test "${min_version#*.}" != "${min_version}"; then
- min_minor_version=${min_version#*.}
- min_minor_version=${min_minor_version%%.*}
- fi
- if test "${min_version#*.*.}" != "${min_version}"; then
- min_point_version=${min_version#*.*.}
- min_point_version=${min_point_version%%.*}
- fi
-
- max_version="$2"
- max_major_version=${max_version%%.*}
- max_minor_version="0"
- max_point_version="0"
- if test "${max_version#*.}" != "${max_version}"; then
- max_minor_version=${max_version#*.}
- max_minor_version=${max_minor_version%%.*}
- fi
- if test "${max_version#*.*.}" != "${max_version}"; then
- max_point_version=${max_version#*.*.}
- max_point_version=${max_point_version%%.*}
- fi
-
- test $(($major_version)) -lt $(($min_major_version)) && exit 1
- if test $(($major_version)) -eq $(($min_major_version)); then
- test $(($minor_version)) -lt $(($min_minor_version)) && exit 1
- if test $(($minor_version)) -eq $(($min_minor_version)); then
- test $(($point_version)) -lt $(($min_point_version)) && exit 1
- fi
- fi
-
- test $(($major_version)) -gt $(($max_major_version)) && exit 1
- if test $(($major_version)) -eq $(($max_major_version)); then
- test $(($minor_version)) -gt $(($max_minor_version)) && exit 1
- if test $(($minor_version)) -eq $(($max_minor_version)); then
- test $(($point_version)) -gt $(($max_point_version)) && exit 1
- fi
- fi
-
- exit 0
-}
-
-# Show the usage line when no arguments are specified.
-if test $# -eq 0; then
- show_usage
- exit 1
-fi
-
-while test $# -gt 0; do
- case $1 in
- --usage) show_usage; exit 0;;
- --help) show_help; exit 0;;
-
- # Installation overrides
- --prefix=*) GTEST_PREFIX=${1#--prefix=};;
- --exec-prefix=*) GTEST_EXEC_PREFIX=${1#--exec-prefix=};;
- --libdir=*) GTEST_LIBDIR=${1#--libdir=};;
- --includedir=*) GTEST_INCLUDEDIR=${1#--includedir=};;
-
- # Installation queries
- --prefix|--exec-prefix|--libdir|--includedir|--version)
- if test -n "${do_query}"; then
- show_usage
- exit 1
- fi
- do_query=${1#--}
- ;;
-
- # Version checking
- --min-version=*)
- do_check_versions=yes
- min_version=${1#--min-version=}
- ;;
- --max-version=*)
- do_check_versions=yes
- max_version=${1#--max-version=}
- ;;
- --exact-version=*)
- do_check_versions=yes
- exact_version=${1#--exact-version=}
- ;;
-
- # Compiler flag output
- --cppflags) echo_cppflags=yes;;
- --cxxflags) echo_cxxflags=yes;;
- --ldflags) echo_ldflags=yes;;
- --libs) echo_libs=yes;;
-
- # Everything else is an error
- *) show_usage; exit 1;;
- esac
- shift
-done
-
-# These have defaults filled in by the configure script but can also be
-# overridden by environment variables or command line parameters.
-prefix="${GTEST_PREFIX:-@prefix@}"
-exec_prefix="${GTEST_EXEC_PREFIX:-@exec_prefix@}"
-libdir="${GTEST_LIBDIR:-@libdir@}"
-includedir="${GTEST_INCLUDEDIR:-@includedir@}"
-
-# We try and detect if our binary is not located at its installed location. If
-# it's not, we provide variables pointing to the source and build tree rather
-# than to the install tree. This allows building against a just-built gtest
-# rather than an installed gtest.
-bindir="@bindir@"
-this_relative_bindir=`dirname $0`
-this_bindir=`cd ${this_relative_bindir}; pwd -P`
-if test "${this_bindir}" = "${this_bindir%${bindir}}"; then
- # The path to the script doesn't end in the bindir sequence from Autoconf,
- # assume that we are in a build tree.
- build_dir=`dirname ${this_bindir}`
- src_dir=`cd ${this_bindir}; cd @top_srcdir@; pwd -P`
-
- # TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we
- # should work to remove it, and/or remove libtool altogether, replacing it
- # with direct references to the library and a link path.
- gtest_libs="${build_dir}/lib/libgtest.la @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
- gtest_ldflags=""
-
- # We provide hooks to include from either the source or build dir, where the
- # build dir is always preferred. This will potentially allow us to write
- # build rules for generated headers and have them automatically be preferred
- # over provided versions.
- gtest_cppflags="-I${build_dir}/include -I${src_dir}/include"
- gtest_cxxflags="@PTHREAD_CFLAGS@"
-else
- # We're using an installed gtest, although it may be staged under some
- # prefix. Assume (as our own libraries do) that we can resolve the prefix,
- # and are present in the dynamic link paths.
- gtest_ldflags="-L${libdir}"
- gtest_libs="-l${name} @PTHREAD_CFLAGS@ @PTHREAD_LIBS@"
- gtest_cppflags="-I${includedir}"
- gtest_cxxflags="@PTHREAD_CFLAGS@"
-fi
-
-# Do an installation query if requested.
-if test -n "$do_query"; then
- case $do_query in
- prefix) echo $prefix; exit 0;;
- exec-prefix) echo $exec_prefix; exit 0;;
- libdir) echo $libdir; exit 0;;
- includedir) echo $includedir; exit 0;;
- version) echo $version; exit 0;;
- *) show_usage; exit 1;;
- esac
-fi
-
-# Do a version check if requested.
-if test "$do_check_versions" = "yes"; then
- # Make sure we didn't receive a bad combination of parameters.
- test "$echo_cppflags" = "yes" && show_usage && exit 1
- test "$echo_cxxflags" = "yes" && show_usage && exit 1
- test "$echo_ldflags" = "yes" && show_usage && exit 1
- test "$echo_libs" = "yes" && show_usage && exit 1
-
- if test "$exact_version" != ""; then
- check_versions $exact_version $exact_version
- # unreachable
- else
- check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999}
- # unreachable
- fi
-fi
-
-# Do the output in the correct order so that these can be used in-line of
-# a compiler invocation.
-output=""
-test "$echo_cppflags" = "yes" && output="$output $gtest_cppflags"
-test "$echo_cxxflags" = "yes" && output="$output $gtest_cxxflags"
-test "$echo_ldflags" = "yes" && output="$output $gtest_ldflags"
-test "$echo_libs" = "yes" && output="$output $gtest_libs"
-echo $output
-
-exit 0
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""pump v0.2.0 - Pretty Useful for Meta Programming.
-
-A tool for preprocessor meta programming. Useful for generating
-repetitive boilerplate code. Especially useful for writing C++
-classes, functions, macros, and templates that need to work with
-various number of arguments.
-
-USAGE:
- pump.py SOURCE_FILE
-
-EXAMPLES:
- pump.py foo.cc.pump
- Converts foo.cc.pump to foo.cc.
-
-GRAMMAR:
- CODE ::= ATOMIC_CODE*
- ATOMIC_CODE ::= $var ID = EXPRESSION
- | $var ID = [[ CODE ]]
- | $range ID EXPRESSION..EXPRESSION
- | $for ID SEPARATOR [[ CODE ]]
- | $($)
- | $ID
- | $(EXPRESSION)
- | $if EXPRESSION [[ CODE ]] ELSE_BRANCH
- | [[ CODE ]]
- | RAW_CODE
- SEPARATOR ::= RAW_CODE | EMPTY
- ELSE_BRANCH ::= $else [[ CODE ]]
- | $elif EXPRESSION [[ CODE ]] ELSE_BRANCH
- | EMPTY
- EXPRESSION has Python syntax.
-"""
-
-__author__ = 'wan@google.com (Zhanyong Wan)'
-
-import os
-import re
-import sys
-
-
-TOKEN_TABLE = [
- (re.compile(r'\$var\s+'), '$var'),
- (re.compile(r'\$elif\s+'), '$elif'),
- (re.compile(r'\$else\s+'), '$else'),
- (re.compile(r'\$for\s+'), '$for'),
- (re.compile(r'\$if\s+'), '$if'),
- (re.compile(r'\$range\s+'), '$range'),
- (re.compile(r'\$[_A-Za-z]\w*'), '$id'),
- (re.compile(r'\$\(\$\)'), '$($)'),
- (re.compile(r'\$'), '$'),
- (re.compile(r'\[\[\n?'), '[['),
- (re.compile(r'\]\]\n?'), ']]'),
- ]
-
-
-class Cursor:
- """Represents a position (line and column) in a text file."""
-
- def __init__(self, line=-1, column=-1):
- self.line = line
- self.column = column
-
- def __eq__(self, rhs):
- return self.line == rhs.line and self.column == rhs.column
-
- def __ne__(self, rhs):
- return not self == rhs
-
- def __lt__(self, rhs):
- return self.line < rhs.line or (
- self.line == rhs.line and self.column < rhs.column)
-
- def __le__(self, rhs):
- return self < rhs or self == rhs
-
- def __gt__(self, rhs):
- return rhs < self
-
- def __ge__(self, rhs):
- return rhs <= self
-
- def __str__(self):
- if self == Eof():
- return 'EOF'
- else:
- return '%s(%s)' % (self.line + 1, self.column)
-
- def __add__(self, offset):
- return Cursor(self.line, self.column + offset)
-
- def __sub__(self, offset):
- return Cursor(self.line, self.column - offset)
-
- def Clone(self):
- """Returns a copy of self."""
-
- return Cursor(self.line, self.column)
-
-
-# Special cursor to indicate the end-of-file.
-def Eof():
- """Returns the special cursor to denote the end-of-file."""
- return Cursor(-1, -1)
-
-
-class Token:
- """Represents a token in a Pump source file."""
-
- def __init__(self, start=None, end=None, value=None, token_type=None):
- if start is None:
- self.start = Eof()
- else:
- self.start = start
- if end is None:
- self.end = Eof()
- else:
- self.end = end
- self.value = value
- self.token_type = token_type
-
- def __str__(self):
- return 'Token @%s: \'%s\' type=%s' % (
- self.start, self.value, self.token_type)
-
- def Clone(self):
- """Returns a copy of self."""
-
- return Token(self.start.Clone(), self.end.Clone(), self.value,
- self.token_type)
-
-
-def StartsWith(lines, pos, string):
- """Returns True iff the given position in lines starts with 'string'."""
-
- return lines[pos.line][pos.column:].startswith(string)
-
-
-def FindFirstInLine(line, token_table):
- best_match_start = -1
- for (regex, token_type) in token_table:
- m = regex.search(line)
- if m:
- # We found regex in lines
- if best_match_start < 0 or m.start() < best_match_start:
- best_match_start = m.start()
- best_match_length = m.end() - m.start()
- best_match_token_type = token_type
-
- if best_match_start < 0:
- return None
-
- return (best_match_start, best_match_length, best_match_token_type)
-
-
-def FindFirst(lines, token_table, cursor):
- """Finds the first occurrence of any string in strings in lines."""
-
- start = cursor.Clone()
- cur_line_number = cursor.line
- for line in lines[start.line:]:
- if cur_line_number == start.line:
- line = line[start.column:]
- m = FindFirstInLine(line, token_table)
- if m:
- # We found a regex in line.
- (start_column, length, token_type) = m
- if cur_line_number == start.line:
- start_column += start.column
- found_start = Cursor(cur_line_number, start_column)
- found_end = found_start + length
- return MakeToken(lines, found_start, found_end, token_type)
- cur_line_number += 1
- # We failed to find str in lines
- return None
-
-
-def SubString(lines, start, end):
- """Returns a substring in lines."""
-
- if end == Eof():
- end = Cursor(len(lines) - 1, len(lines[-1]))
-
- if start >= end:
- return ''
-
- if start.line == end.line:
- return lines[start.line][start.column:end.column]
-
- result_lines = ([lines[start.line][start.column:]] +
- lines[start.line + 1:end.line] +
- [lines[end.line][:end.column]])
- return ''.join(result_lines)
-
-
-def StripMetaComments(str):
- """Strip meta comments from each line in the given string."""
-
- # First, completely remove lines containing nothing but a meta
- # comment, including the trailing \n.
- str = re.sub(r'^\s*\$\$.*\n', '', str)
-
- # Then, remove meta comments from contentful lines.
- return re.sub(r'\s*\$\$.*', '', str)
-
-
-def MakeToken(lines, start, end, token_type):
- """Creates a new instance of Token."""
-
- return Token(start, end, SubString(lines, start, end), token_type)
-
-
-def ParseToken(lines, pos, regex, token_type):
- line = lines[pos.line][pos.column:]
- m = regex.search(line)
- if m and not m.start():
- return MakeToken(lines, pos, pos + m.end(), token_type)
- else:
- print 'ERROR: %s expected at %s.' % (token_type, pos)
- sys.exit(1)
-
-
-ID_REGEX = re.compile(r'[_A-Za-z]\w*')
-EQ_REGEX = re.compile(r'=')
-REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)')
-OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*')
-WHITE_SPACE_REGEX = re.compile(r'\s')
-DOT_DOT_REGEX = re.compile(r'\.\.')
-
-
-def Skip(lines, pos, regex):
- line = lines[pos.line][pos.column:]
- m = re.search(regex, line)
- if m and not m.start():
- return pos + m.end()
- else:
- return pos
-
-
-def SkipUntil(lines, pos, regex, token_type):
- line = lines[pos.line][pos.column:]
- m = re.search(regex, line)
- if m:
- return pos + m.start()
- else:
- print ('ERROR: %s expected on line %s after column %s.' %
- (token_type, pos.line + 1, pos.column))
- sys.exit(1)
-
-
-def ParseExpTokenInParens(lines, pos):
- def ParseInParens(pos):
- pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX)
- pos = Skip(lines, pos, r'\(')
- pos = Parse(pos)
- pos = Skip(lines, pos, r'\)')
- return pos
-
- def Parse(pos):
- pos = SkipUntil(lines, pos, r'\(|\)', ')')
- if SubString(lines, pos, pos + 1) == '(':
- pos = Parse(pos + 1)
- pos = Skip(lines, pos, r'\)')
- return Parse(pos)
- else:
- return pos
-
- start = pos.Clone()
- pos = ParseInParens(pos)
- return MakeToken(lines, start, pos, 'exp')
-
-
-def RStripNewLineFromToken(token):
- if token.value.endswith('\n'):
- return Token(token.start, token.end, token.value[:-1], token.token_type)
- else:
- return token
-
-
-def TokenizeLines(lines, pos):
- while True:
- found = FindFirst(lines, TOKEN_TABLE, pos)
- if not found:
- yield MakeToken(lines, pos, Eof(), 'code')
- return
-
- if found.start == pos:
- prev_token = None
- prev_token_rstripped = None
- else:
- prev_token = MakeToken(lines, pos, found.start, 'code')
- prev_token_rstripped = RStripNewLineFromToken(prev_token)
-
- if found.token_type == '$var':
- if prev_token_rstripped:
- yield prev_token_rstripped
- yield found
- id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
- yield id_token
- pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
-
- eq_token = ParseToken(lines, pos, EQ_REGEX, '=')
- yield eq_token
- pos = Skip(lines, eq_token.end, r'\s*')
-
- if SubString(lines, pos, pos + 2) != '[[':
- exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp')
- yield exp_token
- pos = Cursor(exp_token.end.line + 1, 0)
- elif found.token_type == '$for':
- if prev_token_rstripped:
- yield prev_token_rstripped
- yield found
- id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
- yield id_token
- pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX)
- elif found.token_type == '$range':
- if prev_token_rstripped:
- yield prev_token_rstripped
- yield found
- id_token = ParseToken(lines, found.end, ID_REGEX, 'id')
- yield id_token
- pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX)
-
- dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..')
- yield MakeToken(lines, pos, dots_pos, 'exp')
- yield MakeToken(lines, dots_pos, dots_pos + 2, '..')
- pos = dots_pos + 2
- new_pos = Cursor(pos.line + 1, 0)
- yield MakeToken(lines, pos, new_pos, 'exp')
- pos = new_pos
- elif found.token_type == '$':
- if prev_token:
- yield prev_token
- yield found
- exp_token = ParseExpTokenInParens(lines, found.end)
- yield exp_token
- pos = exp_token.end
- elif (found.token_type == ']]' or found.token_type == '$if' or
- found.token_type == '$elif' or found.token_type == '$else'):
- if prev_token_rstripped:
- yield prev_token_rstripped
- yield found
- pos = found.end
- else:
- if prev_token:
- yield prev_token
- yield found
- pos = found.end
-
-
-def Tokenize(s):
- """A generator that yields the tokens in the given string."""
- if s != '':
- lines = s.splitlines(True)
- for token in TokenizeLines(lines, Cursor(0, 0)):
- yield token
-
-
-class CodeNode:
- def __init__(self, atomic_code_list=None):
- self.atomic_code = atomic_code_list
-
-
-class VarNode:
- def __init__(self, identifier=None, atomic_code=None):
- self.identifier = identifier
- self.atomic_code = atomic_code
-
-
-class RangeNode:
- def __init__(self, identifier=None, exp1=None, exp2=None):
- self.identifier = identifier
- self.exp1 = exp1
- self.exp2 = exp2
-
-
-class ForNode:
- def __init__(self, identifier=None, sep=None, code=None):
- self.identifier = identifier
- self.sep = sep
- self.code = code
-
-
-class ElseNode:
- def __init__(self, else_branch=None):
- self.else_branch = else_branch
-
-
-class IfNode:
- def __init__(self, exp=None, then_branch=None, else_branch=None):
- self.exp = exp
- self.then_branch = then_branch
- self.else_branch = else_branch
-
-
-class RawCodeNode:
- def __init__(self, token=None):
- self.raw_code = token
-
-
-class LiteralDollarNode:
- def __init__(self, token):
- self.token = token
-
-
-class ExpNode:
- def __init__(self, token, python_exp):
- self.token = token
- self.python_exp = python_exp
-
-
-def PopFront(a_list):
- head = a_list[0]
- a_list[:1] = []
- return head
-
-
-def PushFront(a_list, elem):
- a_list[:0] = [elem]
-
-
-def PopToken(a_list, token_type=None):
- token = PopFront(a_list)
- if token_type is not None and token.token_type != token_type:
- print 'ERROR: %s expected at %s' % (token_type, token.start)
- print 'ERROR: %s found instead' % (token,)
- sys.exit(1)
-
- return token
-
-
-def PeekToken(a_list):
- if not a_list:
- return None
-
- return a_list[0]
-
-
-def ParseExpNode(token):
- python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value)
- return ExpNode(token, python_exp)
-
-
-def ParseElseNode(tokens):
- def Pop(token_type=None):
- return PopToken(tokens, token_type)
-
- next = PeekToken(tokens)
- if not next:
- return None
- if next.token_type == '$else':
- Pop('$else')
- Pop('[[')
- code_node = ParseCodeNode(tokens)
- Pop(']]')
- return code_node
- elif next.token_type == '$elif':
- Pop('$elif')
- exp = Pop('code')
- Pop('[[')
- code_node = ParseCodeNode(tokens)
- Pop(']]')
- inner_else_node = ParseElseNode(tokens)
- return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)])
- elif not next.value.strip():
- Pop('code')
- return ParseElseNode(tokens)
- else:
- return None
-
-
-def ParseAtomicCodeNode(tokens):
- def Pop(token_type=None):
- return PopToken(tokens, token_type)
-
- head = PopFront(tokens)
- t = head.token_type
- if t == 'code':
- return RawCodeNode(head)
- elif t == '$var':
- id_token = Pop('id')
- Pop('=')
- next = PeekToken(tokens)
- if next.token_type == 'exp':
- exp_token = Pop()
- return VarNode(id_token, ParseExpNode(exp_token))
- Pop('[[')
- code_node = ParseCodeNode(tokens)
- Pop(']]')
- return VarNode(id_token, code_node)
- elif t == '$for':
- id_token = Pop('id')
- next_token = PeekToken(tokens)
- if next_token.token_type == 'code':
- sep_token = next_token
- Pop('code')
- else:
- sep_token = None
- Pop('[[')
- code_node = ParseCodeNode(tokens)
- Pop(']]')
- return ForNode(id_token, sep_token, code_node)
- elif t == '$if':
- exp_token = Pop('code')
- Pop('[[')
- code_node = ParseCodeNode(tokens)
- Pop(']]')
- else_node = ParseElseNode(tokens)
- return IfNode(ParseExpNode(exp_token), code_node, else_node)
- elif t == '$range':
- id_token = Pop('id')
- exp1_token = Pop('exp')
- Pop('..')
- exp2_token = Pop('exp')
- return RangeNode(id_token, ParseExpNode(exp1_token),
- ParseExpNode(exp2_token))
- elif t == '$id':
- return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id'))
- elif t == '$($)':
- return LiteralDollarNode(head)
- elif t == '$':
- exp_token = Pop('exp')
- return ParseExpNode(exp_token)
- elif t == '[[':
- code_node = ParseCodeNode(tokens)
- Pop(']]')
- return code_node
- else:
- PushFront(tokens, head)
- return None
-
-
-def ParseCodeNode(tokens):
- atomic_code_list = []
- while True:
- if not tokens:
- break
- atomic_code_node = ParseAtomicCodeNode(tokens)
- if atomic_code_node:
- atomic_code_list.append(atomic_code_node)
- else:
- break
- return CodeNode(atomic_code_list)
-
-
-def ParseToAST(pump_src_text):
- """Convert the given Pump source text into an AST."""
- tokens = list(Tokenize(pump_src_text))
- code_node = ParseCodeNode(tokens)
- return code_node
-
-
-class Env:
- def __init__(self):
- self.variables = []
- self.ranges = []
-
- def Clone(self):
- clone = Env()
- clone.variables = self.variables[:]
- clone.ranges = self.ranges[:]
- return clone
-
- def PushVariable(self, var, value):
- # If value looks like an int, store it as an int.
- try:
- int_value = int(value)
- if ('%s' % int_value) == value:
- value = int_value
- except Exception:
- pass
- self.variables[:0] = [(var, value)]
-
- def PopVariable(self):
- self.variables[:1] = []
-
- def PushRange(self, var, lower, upper):
- self.ranges[:0] = [(var, lower, upper)]
-
- def PopRange(self):
- self.ranges[:1] = []
-
- def GetValue(self, identifier):
- for (var, value) in self.variables:
- if identifier == var:
- return value
-
- print 'ERROR: meta variable %s is undefined.' % (identifier,)
- sys.exit(1)
-
- def EvalExp(self, exp):
- try:
- result = eval(exp.python_exp)
- except Exception, e:
- print 'ERROR: caught exception %s: %s' % (e.__class__.__name__, e)
- print ('ERROR: failed to evaluate meta expression %s at %s' %
- (exp.python_exp, exp.token.start))
- sys.exit(1)
- return result
-
- def GetRange(self, identifier):
- for (var, lower, upper) in self.ranges:
- if identifier == var:
- return (lower, upper)
-
- print 'ERROR: range %s is undefined.' % (identifier,)
- sys.exit(1)
-
-
-class Output:
- def __init__(self):
- self.string = ''
-
- def GetLastLine(self):
- index = self.string.rfind('\n')
- if index < 0:
- return ''
-
- return self.string[index + 1:]
-
- def Append(self, s):
- self.string += s
-
-
-def RunAtomicCode(env, node, output):
- if isinstance(node, VarNode):
- identifier = node.identifier.value.strip()
- result = Output()
- RunAtomicCode(env.Clone(), node.atomic_code, result)
- value = result.string
- env.PushVariable(identifier, value)
- elif isinstance(node, RangeNode):
- identifier = node.identifier.value.strip()
- lower = int(env.EvalExp(node.exp1))
- upper = int(env.EvalExp(node.exp2))
- env.PushRange(identifier, lower, upper)
- elif isinstance(node, ForNode):
- identifier = node.identifier.value.strip()
- if node.sep is None:
- sep = ''
- else:
- sep = node.sep.value
- (lower, upper) = env.GetRange(identifier)
- for i in range(lower, upper + 1):
- new_env = env.Clone()
- new_env.PushVariable(identifier, i)
- RunCode(new_env, node.code, output)
- if i != upper:
- output.Append(sep)
- elif isinstance(node, RawCodeNode):
- output.Append(node.raw_code.value)
- elif isinstance(node, IfNode):
- cond = env.EvalExp(node.exp)
- if cond:
- RunCode(env.Clone(), node.then_branch, output)
- elif node.else_branch is not None:
- RunCode(env.Clone(), node.else_branch, output)
- elif isinstance(node, ExpNode):
- value = env.EvalExp(node)
- output.Append('%s' % (value,))
- elif isinstance(node, LiteralDollarNode):
- output.Append('$')
- elif isinstance(node, CodeNode):
- RunCode(env.Clone(), node, output)
- else:
- print 'BAD'
- print node
- sys.exit(1)
-
-
-def RunCode(env, code_node, output):
- for atomic_code in code_node.atomic_code:
- RunAtomicCode(env, atomic_code, output)
-
-
-def IsSingleLineComment(cur_line):
- return '//' in cur_line
-
-
-def IsInPreprocessorDirective(prev_lines, cur_line):
- if cur_line.lstrip().startswith('#'):
- return True
- return prev_lines and prev_lines[-1].endswith('\\')
-
-
-def WrapComment(line, output):
- loc = line.find('//')
- before_comment = line[:loc].rstrip()
- if before_comment == '':
- indent = loc
- else:
- output.append(before_comment)
- indent = len(before_comment) - len(before_comment.lstrip())
- prefix = indent*' ' + '// '
- max_len = 80 - len(prefix)
- comment = line[loc + 2:].strip()
- segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != '']
- cur_line = ''
- for seg in segs:
- if len((cur_line + seg).rstrip()) < max_len:
- cur_line += seg
- else:
- if cur_line.strip() != '':
- output.append(prefix + cur_line.rstrip())
- cur_line = seg.lstrip()
- if cur_line.strip() != '':
- output.append(prefix + cur_line.strip())
-
-
-def WrapCode(line, line_concat, output):
- indent = len(line) - len(line.lstrip())
- prefix = indent*' ' # Prefix of the current line
- max_len = 80 - indent - len(line_concat) # Maximum length of the current line
- new_prefix = prefix + 4*' ' # Prefix of a continuation line
- new_max_len = max_len - 4 # Maximum length of a continuation line
- # Prefers to wrap a line after a ',' or ';'.
- segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != '']
- cur_line = '' # The current line without leading spaces.
- for seg in segs:
- # If the line is still too long, wrap at a space.
- while cur_line == '' and len(seg.strip()) > max_len:
- seg = seg.lstrip()
- split_at = seg.rfind(' ', 0, max_len)
- output.append(prefix + seg[:split_at].strip() + line_concat)
- seg = seg[split_at + 1:]
- prefix = new_prefix
- max_len = new_max_len
-
- if len((cur_line + seg).rstrip()) < max_len:
- cur_line = (cur_line + seg).lstrip()
- else:
- output.append(prefix + cur_line.rstrip() + line_concat)
- prefix = new_prefix
- max_len = new_max_len
- cur_line = seg.lstrip()
- if cur_line.strip() != '':
- output.append(prefix + cur_line.strip())
-
-
-def WrapPreprocessorDirective(line, output):
- WrapCode(line, ' \\', output)
-
-
-def WrapPlainCode(line, output):
- WrapCode(line, '', output)
-
-
-def IsMultiLineIWYUPragma(line):
- return re.search(r'/\* IWYU pragma: ', line)
-
-
-def IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
- return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or
- re.match(r'^#include\s', line) or
- # Don't break IWYU pragmas, either; that causes iwyu.py problems.
- re.search(r'// IWYU pragma: ', line))
-
-
-def WrapLongLine(line, output):
- line = line.rstrip()
- if len(line) <= 80:
- output.append(line)
- elif IsSingleLineComment(line):
- if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
- # The style guide made an exception to allow long header guard lines,
- # includes and IWYU pragmas.
- output.append(line)
- else:
- WrapComment(line, output)
- elif IsInPreprocessorDirective(output, line):
- if IsHeaderGuardIncludeOrOneLineIWYUPragma(line):
- # The style guide made an exception to allow long header guard lines,
- # includes and IWYU pragmas.
- output.append(line)
- else:
- WrapPreprocessorDirective(line, output)
- elif IsMultiLineIWYUPragma(line):
- output.append(line)
- else:
- WrapPlainCode(line, output)
-
-
-def BeautifyCode(string):
- lines = string.splitlines()
- output = []
- for line in lines:
- WrapLongLine(line, output)
- output2 = [line.rstrip() for line in output]
- return '\n'.join(output2) + '\n'
-
-
-def ConvertFromPumpSource(src_text):
- """Return the text generated from the given Pump source text."""
- ast = ParseToAST(StripMetaComments(src_text))
- output = Output()
- RunCode(Env(), ast, output)
- return BeautifyCode(output.string)
-
-
-def main(argv):
- if len(argv) == 1:
- print __doc__
- sys.exit(1)
-
- file_path = argv[-1]
- output_str = ConvertFromPumpSource(file(file_path, 'r').read())
- if file_path.endswith('.pump'):
- output_file_path = file_path[:-5]
- else:
- output_file_path = '-'
- if output_file_path == '-':
- print output_str,
- else:
- output_file = file(output_file_path, 'w')
- output_file.write('// This file was GENERATED by command:\n')
- output_file.write('// %s %s\n' %
- (os.path.basename(__file__), os.path.basename(file_path)))
- output_file.write('// DO NOT EDIT BY HAND!!!\n\n')
- output_file.write(output_str)
- output_file.close()
-
-
-if __name__ == '__main__':
- main(sys.argv)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2013 Google Inc. All Rights Reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Script for branching Google Test/Mock wiki pages for a new version.
-
-SYNOPSIS
- release_docs.py NEW_RELEASE_VERSION
-
- Google Test and Google Mock's external user documentation is in
- interlinked wiki files. When we release a new version of
- Google Test or Google Mock, we need to branch the wiki files
- such that users of a specific version of Google Test/Mock can
- look up documenation relevant for that version. This script
- automates that process by:
-
- - branching the current wiki pages (which document the
- behavior of the SVN trunk head) to pages for the specified
- version (e.g. branching FAQ.wiki to V2_6_FAQ.wiki when
- NEW_RELEASE_VERSION is 2.6);
- - updating the links in the branched files to point to the branched
- version (e.g. a link in V2_6_FAQ.wiki that pointed to
- Primer.wiki#Anchor will now point to V2_6_Primer.wiki#Anchor).
-
- NOTE: NEW_RELEASE_VERSION must be a NEW version number for
- which the wiki pages don't yet exist; otherwise you'll get SVN
- errors like "svn: Path 'V1_7_PumpManual.wiki' is not a
- directory" when running the script.
-
-EXAMPLE
- $ cd PATH/TO/GTEST_SVN_WORKSPACE/trunk
- $ scripts/release_docs.py 2.6 # create wiki pages for v2.6
- $ svn status # verify the file list
- $ svn diff # verify the file contents
- $ svn commit -m "release wiki pages for v2.6"
-"""
-
-__author__ = 'wan@google.com (Zhanyong Wan)'
-
-import os
-import re
-import sys
-
-import common
-
-
-# Wiki pages that shouldn't be branched for every gtest/gmock release.
-GTEST_UNVERSIONED_WIKIS = ['DevGuide.wiki']
-GMOCK_UNVERSIONED_WIKIS = [
- 'DesignDoc.wiki',
- 'DevGuide.wiki',
- 'KnownIssues.wiki'
- ]
-
-
-def DropWikiSuffix(wiki_filename):
- """Removes the .wiki suffix (if any) from the given filename."""
-
- return (wiki_filename[:-len('.wiki')] if wiki_filename.endswith('.wiki')
- else wiki_filename)
-
-
-class WikiBrancher(object):
- """Branches ..."""
-
- def __init__(self, dot_version):
- self.project, svn_root_path = common.GetSvnInfo()
- if self.project not in ('googletest', 'googlemock'):
- sys.exit('This script must be run in a gtest or gmock SVN workspace.')
- self.wiki_dir = svn_root_path + '/wiki'
- # Turn '2.6' to 'V2_6_'.
- self.version_prefix = 'V' + dot_version.replace('.', '_') + '_'
- self.files_to_branch = self.GetFilesToBranch()
- page_names = [DropWikiSuffix(f) for f in self.files_to_branch]
- # A link to Foo.wiki is in one of the following forms:
- # [Foo words]
- # [Foo#Anchor words]
- # [http://code.google.com/.../wiki/Foo words]
- # [http://code.google.com/.../wiki/Foo#Anchor words]
- # We want to replace 'Foo' with 'V2_6_Foo' in the above cases.
- self.search_for_re = re.compile(
- # This regex matches either
- # [Foo
- # or
- # /wiki/Foo
- # followed by a space or a #, where Foo is the name of an
- # unversioned wiki page.
- r'(\[|/wiki/)(%s)([ #])' % '|'.join(page_names))
- self.replace_with = r'\1%s\2\3' % (self.version_prefix,)
-
- def GetFilesToBranch(self):
- """Returns a list of .wiki file names that need to be branched."""
-
- unversioned_wikis = (GTEST_UNVERSIONED_WIKIS if self.project == 'googletest'
- else GMOCK_UNVERSIONED_WIKIS)
- return [f for f in os.listdir(self.wiki_dir)
- if (f.endswith('.wiki') and
- not re.match(r'^V\d', f) and # Excluded versioned .wiki files.
- f not in unversioned_wikis)]
-
- def BranchFiles(self):
- """Branches the .wiki files needed to be branched."""
-
- print 'Branching %d .wiki files:' % (len(self.files_to_branch),)
- os.chdir(self.wiki_dir)
- for f in self.files_to_branch:
- command = 'svn cp %s %s%s' % (f, self.version_prefix, f)
- print command
- os.system(command)
-
- def UpdateLinksInBranchedFiles(self):
-
- for f in self.files_to_branch:
- source_file = os.path.join(self.wiki_dir, f)
- versioned_file = os.path.join(self.wiki_dir, self.version_prefix + f)
- print 'Updating links in %s.' % (versioned_file,)
- text = file(source_file, 'r').read()
- new_text = self.search_for_re.sub(self.replace_with, text)
- file(versioned_file, 'w').write(new_text)
-
-
-def main():
- if len(sys.argv) != 2:
- sys.exit(__doc__)
-
- brancher = WikiBrancher(sys.argv[1])
- brancher.BranchFiles()
- brancher.UpdateLinksInBranchedFiles()
-
-
-if __name__ == '__main__':
- main()
+++ /dev/null
-# A Makefile for fusing Google Test and building a sample test against it.
-#
-# SYNOPSIS:
-#
-# make [all] - makes everything.
-# make TARGET - makes the given target.
-# make check - makes everything and runs the built sample test.
-# make clean - removes all files generated by make.
-
-# Points to the root of fused Google Test, relative to where this file is.
-FUSED_GTEST_DIR = output
-
-# Paths to the fused gtest files.
-FUSED_GTEST_H = $(FUSED_GTEST_DIR)/gtest/gtest.h
-FUSED_GTEST_ALL_CC = $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
-
-# Where to find the sample test.
-SAMPLE_DIR = ../../samples
-
-# Where to find gtest_main.cc.
-GTEST_MAIN_CC = ../../src/gtest_main.cc
-
-# Flags passed to the preprocessor.
-# We have no idea here whether pthreads is available in the system, so
-# disable its use.
-CPPFLAGS += -I$(FUSED_GTEST_DIR) -DGTEST_HAS_PTHREAD=0
-
-# Flags passed to the C++ compiler.
-CXXFLAGS += -g
-
-all : sample1_unittest
-
-check : all
- ./sample1_unittest
-
-clean :
- rm -rf $(FUSED_GTEST_DIR) sample1_unittest *.o
-
-$(FUSED_GTEST_H) :
- ../fuse_gtest_files.py $(FUSED_GTEST_DIR)
-
-$(FUSED_GTEST_ALL_CC) :
- ../fuse_gtest_files.py $(FUSED_GTEST_DIR)
-
-gtest-all.o : $(FUSED_GTEST_H) $(FUSED_GTEST_ALL_CC)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(FUSED_GTEST_DIR)/gtest/gtest-all.cc
-
-gtest_main.o : $(FUSED_GTEST_H) $(GTEST_MAIN_CC)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_MAIN_CC)
-
-sample1.o : $(SAMPLE_DIR)/sample1.cc $(SAMPLE_DIR)/sample1.h
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1.cc
-
-sample1_unittest.o : $(SAMPLE_DIR)/sample1_unittest.cc \
- $(SAMPLE_DIR)/sample1.h $(FUSED_GTEST_H)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(SAMPLE_DIR)/sample1_unittest.cc
-
-sample1_unittest : sample1.o sample1_unittest.o gtest-all.o gtest_main.o
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -o $@
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2007 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Tool for uploading diffs from a version control system to the codereview app.
-
-Usage summary: upload.py [options] [-- diff_options]
-
-Diff options are passed to the diff command of the underlying system.
-
-Supported version control systems:
- Git
- Mercurial
- Subversion
-
-It is important for Git/Mercurial users to specify a tree/node/branch to diff
-against by using the '--rev' option.
-"""
-# This code is derived from appcfg.py in the App Engine SDK (open source),
-# and from ASPN recipe #146306.
-
-import cookielib
-import getpass
-import logging
-import md5
-import mimetypes
-import optparse
-import os
-import re
-import socket
-import subprocess
-import sys
-import urllib
-import urllib2
-import urlparse
-
-try:
- import readline
-except ImportError:
- pass
-
-# The logging verbosity:
-# 0: Errors only.
-# 1: Status messages.
-# 2: Info logs.
-# 3: Debug logs.
-verbosity = 1
-
-# Max size of patch or base file.
-MAX_UPLOAD_SIZE = 900 * 1024
-
-
-def GetEmail(prompt):
- """Prompts the user for their email address and returns it.
-
- The last used email address is saved to a file and offered up as a suggestion
- to the user. If the user presses enter without typing in anything the last
- used email address is used. If the user enters a new address, it is saved
- for next time we prompt.
-
- """
- last_email_file_name = os.path.expanduser("~/.last_codereview_email_address")
- last_email = ""
- if os.path.exists(last_email_file_name):
- try:
- last_email_file = open(last_email_file_name, "r")
- last_email = last_email_file.readline().strip("\n")
- last_email_file.close()
- prompt += " [%s]" % last_email
- except IOError, e:
- pass
- email = raw_input(prompt + ": ").strip()
- if email:
- try:
- last_email_file = open(last_email_file_name, "w")
- last_email_file.write(email)
- last_email_file.close()
- except IOError, e:
- pass
- else:
- email = last_email
- return email
-
-
-def StatusUpdate(msg):
- """Print a status message to stdout.
-
- If 'verbosity' is greater than 0, print the message.
-
- Args:
- msg: The string to print.
- """
- if verbosity > 0:
- print msg
-
-
-def ErrorExit(msg):
- """Print an error message to stderr and exit."""
- print >>sys.stderr, msg
- sys.exit(1)
-
-
-class ClientLoginError(urllib2.HTTPError):
- """Raised to indicate there was an error authenticating with ClientLogin."""
-
- def __init__(self, url, code, msg, headers, args):
- urllib2.HTTPError.__init__(self, url, code, msg, headers, None)
- self.args = args
- self.reason = args["Error"]
-
-
-class AbstractRpcServer(object):
- """Provides a common interface for a simple RPC server."""
-
- def __init__(self, host, auth_function, host_override=None, extra_headers={},
- save_cookies=False):
- """Creates a new HttpRpcServer.
-
- Args:
- host: The host to send requests to.
- auth_function: A function that takes no arguments and returns an
- (email, password) tuple when called. Will be called if authentication
- is required.
- host_override: The host header to send to the server (defaults to host).
- extra_headers: A dict of extra headers to append to every request.
- save_cookies: If True, save the authentication cookies to local disk.
- If False, use an in-memory cookiejar instead. Subclasses must
- implement this functionality. Defaults to False.
- """
- self.host = host
- self.host_override = host_override
- self.auth_function = auth_function
- self.authenticated = False
- self.extra_headers = extra_headers
- self.save_cookies = save_cookies
- self.opener = self._GetOpener()
- if self.host_override:
- logging.info("Server: %s; Host: %s", self.host, self.host_override)
- else:
- logging.info("Server: %s", self.host)
-
- def _GetOpener(self):
- """Returns an OpenerDirector for making HTTP requests.
-
- Returns:
- A urllib2.OpenerDirector object.
- """
- raise NotImplementedError()
-
- def _CreateRequest(self, url, data=None):
- """Creates a new urllib request."""
- logging.debug("Creating request for: '%s' with payload:\n%s", url, data)
- req = urllib2.Request(url, data=data)
- if self.host_override:
- req.add_header("Host", self.host_override)
- for key, value in self.extra_headers.iteritems():
- req.add_header(key, value)
- return req
-
- def _GetAuthToken(self, email, password):
- """Uses ClientLogin to authenticate the user, returning an auth token.
-
- Args:
- email: The user's email address
- password: The user's password
-
- Raises:
- ClientLoginError: If there was an error authenticating with ClientLogin.
- HTTPError: If there was some other form of HTTP error.
-
- Returns:
- The authentication token returned by ClientLogin.
- """
- account_type = "GOOGLE"
- if self.host.endswith(".google.com"):
- # Needed for use inside Google.
- account_type = "HOSTED"
- req = self._CreateRequest(
- url="https://www.google.com/accounts/ClientLogin",
- data=urllib.urlencode({
- "Email": email,
- "Passwd": password,
- "service": "ah",
- "source": "rietveld-codereview-upload",
- "accountType": account_type,
- }),
- )
- try:
- response = self.opener.open(req)
- response_body = response.read()
- response_dict = dict(x.split("=")
- for x in response_body.split("\n") if x)
- return response_dict["Auth"]
- except urllib2.HTTPError, e:
- if e.code == 403:
- body = e.read()
- response_dict = dict(x.split("=", 1) for x in body.split("\n") if x)
- raise ClientLoginError(req.get_full_url(), e.code, e.msg,
- e.headers, response_dict)
- else:
- raise
-
- def _GetAuthCookie(self, auth_token):
- """Fetches authentication cookies for an authentication token.
-
- Args:
- auth_token: The authentication token returned by ClientLogin.
-
- Raises:
- HTTPError: If there was an error fetching the authentication cookies.
- """
- # This is a dummy value to allow us to identify when we're successful.
- continue_location = "http://localhost/"
- args = {"continue": continue_location, "auth": auth_token}
- req = self._CreateRequest("http://%s/_ah/login?%s" %
- (self.host, urllib.urlencode(args)))
- try:
- response = self.opener.open(req)
- except urllib2.HTTPError, e:
- response = e
- if (response.code != 302 or
- response.info()["location"] != continue_location):
- raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg,
- response.headers, response.fp)
- self.authenticated = True
-
- def _Authenticate(self):
- """Authenticates the user.
-
- The authentication process works as follows:
- 1) We get a username and password from the user
- 2) We use ClientLogin to obtain an AUTH token for the user
- (see https://developers.google.com/identity/protocols/AuthForInstalledApps).
- 3) We pass the auth token to /_ah/login on the server to obtain an
- authentication cookie. If login was successful, it tries to redirect
- us to the URL we provided.
-
- If we attempt to access the upload API without first obtaining an
- authentication cookie, it returns a 401 response and directs us to
- authenticate ourselves with ClientLogin.
- """
- for i in range(3):
- credentials = self.auth_function()
- try:
- auth_token = self._GetAuthToken(credentials[0], credentials[1])
- except ClientLoginError, e:
- if e.reason == "BadAuthentication":
- print >>sys.stderr, "Invalid username or password."
- continue
- if e.reason == "CaptchaRequired":
- print >>sys.stderr, (
- "Please go to\n"
- "https://www.google.com/accounts/DisplayUnlockCaptcha\n"
- "and verify you are a human. Then try again.")
- break
- if e.reason == "NotVerified":
- print >>sys.stderr, "Account not verified."
- break
- if e.reason == "TermsNotAgreed":
- print >>sys.stderr, "User has not agreed to TOS."
- break
- if e.reason == "AccountDeleted":
- print >>sys.stderr, "The user account has been deleted."
- break
- if e.reason == "AccountDisabled":
- print >>sys.stderr, "The user account has been disabled."
- break
- if e.reason == "ServiceDisabled":
- print >>sys.stderr, ("The user's access to the service has been "
- "disabled.")
- break
- if e.reason == "ServiceUnavailable":
- print >>sys.stderr, "The service is not available; try again later."
- break
- raise
- self._GetAuthCookie(auth_token)
- return
-
- def Send(self, request_path, payload=None,
- content_type="application/octet-stream",
- timeout=None,
- **kwargs):
- """Sends an RPC and returns the response.
-
- Args:
- request_path: The path to send the request to, eg /api/appversion/create.
- payload: The body of the request, or None to send an empty request.
- content_type: The Content-Type header to use.
- timeout: timeout in seconds; default None i.e. no timeout.
- (Note: for large requests on OS X, the timeout doesn't work right.)
- kwargs: Any keyword arguments are converted into query string parameters.
-
- Returns:
- The response body, as a string.
- """
- # TODO: Don't require authentication. Let the server say
- # whether it is necessary.
- if not self.authenticated:
- self._Authenticate()
-
- old_timeout = socket.getdefaulttimeout()
- socket.setdefaulttimeout(timeout)
- try:
- tries = 0
- while True:
- tries += 1
- args = dict(kwargs)
- url = "http://%s%s" % (self.host, request_path)
- if args:
- url += "?" + urllib.urlencode(args)
- req = self._CreateRequest(url=url, data=payload)
- req.add_header("Content-Type", content_type)
- try:
- f = self.opener.open(req)
- response = f.read()
- f.close()
- return response
- except urllib2.HTTPError, e:
- if tries > 3:
- raise
- elif e.code == 401:
- self._Authenticate()
-## elif e.code >= 500 and e.code < 600:
-## # Server Error - try again.
-## continue
- else:
- raise
- finally:
- socket.setdefaulttimeout(old_timeout)
-
-
-class HttpRpcServer(AbstractRpcServer):
- """Provides a simplified RPC-style interface for HTTP requests."""
-
- def _Authenticate(self):
- """Save the cookie jar after authentication."""
- super(HttpRpcServer, self)._Authenticate()
- if self.save_cookies:
- StatusUpdate("Saving authentication cookies to %s" % self.cookie_file)
- self.cookie_jar.save()
-
- def _GetOpener(self):
- """Returns an OpenerDirector that supports cookies and ignores redirects.
-
- Returns:
- A urllib2.OpenerDirector object.
- """
- opener = urllib2.OpenerDirector()
- opener.add_handler(urllib2.ProxyHandler())
- opener.add_handler(urllib2.UnknownHandler())
- opener.add_handler(urllib2.HTTPHandler())
- opener.add_handler(urllib2.HTTPDefaultErrorHandler())
- opener.add_handler(urllib2.HTTPSHandler())
- opener.add_handler(urllib2.HTTPErrorProcessor())
- if self.save_cookies:
- self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies")
- self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file)
- if os.path.exists(self.cookie_file):
- try:
- self.cookie_jar.load()
- self.authenticated = True
- StatusUpdate("Loaded authentication cookies from %s" %
- self.cookie_file)
- except (cookielib.LoadError, IOError):
- # Failed to load cookies - just ignore them.
- pass
- else:
- # Create an empty cookie file with mode 600
- fd = os.open(self.cookie_file, os.O_CREAT, 0600)
- os.close(fd)
- # Always chmod the cookie file
- os.chmod(self.cookie_file, 0600)
- else:
- # Don't save cookies across runs of update.py.
- self.cookie_jar = cookielib.CookieJar()
- opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))
- return opener
-
-
-parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]")
-parser.add_option("-y", "--assume_yes", action="store_true",
- dest="assume_yes", default=False,
- help="Assume that the answer to yes/no questions is 'yes'.")
-# Logging
-group = parser.add_option_group("Logging options")
-group.add_option("-q", "--quiet", action="store_const", const=0,
- dest="verbose", help="Print errors only.")
-group.add_option("-v", "--verbose", action="store_const", const=2,
- dest="verbose", default=1,
- help="Print info level logs (default).")
-group.add_option("--noisy", action="store_const", const=3,
- dest="verbose", help="Print all logs.")
-# Review server
-group = parser.add_option_group("Review server options")
-group.add_option("-s", "--server", action="store", dest="server",
- default="codereview.appspot.com",
- metavar="SERVER",
- help=("The server to upload to. The format is host[:port]. "
- "Defaults to 'codereview.appspot.com'."))
-group.add_option("-e", "--email", action="store", dest="email",
- metavar="EMAIL", default=None,
- help="The username to use. Will prompt if omitted.")
-group.add_option("-H", "--host", action="store", dest="host",
- metavar="HOST", default=None,
- help="Overrides the Host header sent with all RPCs.")
-group.add_option("--no_cookies", action="store_false",
- dest="save_cookies", default=True,
- help="Do not save authentication cookies to local disk.")
-# Issue
-group = parser.add_option_group("Issue options")
-group.add_option("-d", "--description", action="store", dest="description",
- metavar="DESCRIPTION", default=None,
- help="Optional description when creating an issue.")
-group.add_option("-f", "--description_file", action="store",
- dest="description_file", metavar="DESCRIPTION_FILE",
- default=None,
- help="Optional path of a file that contains "
- "the description when creating an issue.")
-group.add_option("-r", "--reviewers", action="store", dest="reviewers",
- metavar="REVIEWERS", default=None,
- help="Add reviewers (comma separated email addresses).")
-group.add_option("--cc", action="store", dest="cc",
- metavar="CC", default=None,
- help="Add CC (comma separated email addresses).")
-# Upload options
-group = parser.add_option_group("Patch options")
-group.add_option("-m", "--message", action="store", dest="message",
- metavar="MESSAGE", default=None,
- help="A message to identify the patch. "
- "Will prompt if omitted.")
-group.add_option("-i", "--issue", type="int", action="store",
- metavar="ISSUE", default=None,
- help="Issue number to which to add. Defaults to new issue.")
-group.add_option("--download_base", action="store_true",
- dest="download_base", default=False,
- help="Base files will be downloaded by the server "
- "(side-by-side diffs may not work on files with CRs).")
-group.add_option("--rev", action="store", dest="revision",
- metavar="REV", default=None,
- help="Branch/tree/revision to diff against (used by DVCS).")
-group.add_option("--send_mail", action="store_true",
- dest="send_mail", default=False,
- help="Send notification email to reviewers.")
-
-
-def GetRpcServer(options):
- """Returns an instance of an AbstractRpcServer.
-
- Returns:
- A new AbstractRpcServer, on which RPC calls can be made.
- """
-
- rpc_server_class = HttpRpcServer
-
- def GetUserCredentials():
- """Prompts the user for a username and password."""
- email = options.email
- if email is None:
- email = GetEmail("Email (login for uploading to %s)" % options.server)
- password = getpass.getpass("Password for %s: " % email)
- return (email, password)
-
- # If this is the dev_appserver, use fake authentication.
- host = (options.host or options.server).lower()
- if host == "localhost" or host.startswith("localhost:"):
- email = options.email
- if email is None:
- email = "test@example.com"
- logging.info("Using debug user %s. Override with --email" % email)
- server = rpc_server_class(
- options.server,
- lambda: (email, "password"),
- host_override=options.host,
- extra_headers={"Cookie":
- 'dev_appserver_login="%s:False"' % email},
- save_cookies=options.save_cookies)
- # Don't try to talk to ClientLogin.
- server.authenticated = True
- return server
-
- return rpc_server_class(options.server, GetUserCredentials,
- host_override=options.host,
- save_cookies=options.save_cookies)
-
-
-def EncodeMultipartFormData(fields, files):
- """Encode form fields for multipart/form-data.
-
- Args:
- fields: A sequence of (name, value) elements for regular form fields.
- files: A sequence of (name, filename, value) elements for data to be
- uploaded as files.
- Returns:
- (content_type, body) ready for httplib.HTTP instance.
-
- Source:
- https://web.archive.org/web/20160116052001/code.activestate.com/recipes/146306
- """
- BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-'
- CRLF = '\r\n'
- lines = []
- for (key, value) in fields:
- lines.append('--' + BOUNDARY)
- lines.append('Content-Disposition: form-data; name="%s"' % key)
- lines.append('')
- lines.append(value)
- for (key, filename, value) in files:
- lines.append('--' + BOUNDARY)
- lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
- (key, filename))
- lines.append('Content-Type: %s' % GetContentType(filename))
- lines.append('')
- lines.append(value)
- lines.append('--' + BOUNDARY + '--')
- lines.append('')
- body = CRLF.join(lines)
- content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
- return content_type, body
-
-
-def GetContentType(filename):
- """Helper to guess the content-type from the filename."""
- return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
-
-
-# Use a shell for subcommands on Windows to get a PATH search.
-use_shell = sys.platform.startswith("win")
-
-def RunShellWithReturnCode(command, print_output=False,
- universal_newlines=True):
- """Executes a command and returns the output from stdout and the return code.
-
- Args:
- command: Command to execute.
- print_output: If True, the output is printed to stdout.
- If False, both stdout and stderr are ignored.
- universal_newlines: Use universal_newlines flag (default: True).
-
- Returns:
- Tuple (output, return code)
- """
- logging.info("Running %s", command)
- p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- shell=use_shell, universal_newlines=universal_newlines)
- if print_output:
- output_array = []
- while True:
- line = p.stdout.readline()
- if not line:
- break
- print line.strip("\n")
- output_array.append(line)
- output = "".join(output_array)
- else:
- output = p.stdout.read()
- p.wait()
- errout = p.stderr.read()
- if print_output and errout:
- print >>sys.stderr, errout
- p.stdout.close()
- p.stderr.close()
- return output, p.returncode
-
-
-def RunShell(command, silent_ok=False, universal_newlines=True,
- print_output=False):
- data, retcode = RunShellWithReturnCode(command, print_output,
- universal_newlines)
- if retcode:
- ErrorExit("Got error status from %s:\n%s" % (command, data))
- if not silent_ok and not data:
- ErrorExit("No output from %s" % command)
- return data
-
-
-class VersionControlSystem(object):
- """Abstract base class providing an interface to the VCS."""
-
- def __init__(self, options):
- """Constructor.
-
- Args:
- options: Command line options.
- """
- self.options = options
-
- def GenerateDiff(self, args):
- """Return the current diff as a string.
-
- Args:
- args: Extra arguments to pass to the diff command.
- """
- raise NotImplementedError(
- "abstract method -- subclass %s must override" % self.__class__)
-
- def GetUnknownFiles(self):
- """Return a list of files unknown to the VCS."""
- raise NotImplementedError(
- "abstract method -- subclass %s must override" % self.__class__)
-
- def CheckForUnknownFiles(self):
- """Show an "are you sure?" prompt if there are unknown files."""
- unknown_files = self.GetUnknownFiles()
- if unknown_files:
- print "The following files are not added to version control:"
- for line in unknown_files:
- print line
- prompt = "Are you sure to continue?(y/N) "
- answer = raw_input(prompt).strip()
- if answer != "y":
- ErrorExit("User aborted")
-
- def GetBaseFile(self, filename):
- """Get the content of the upstream version of a file.
-
- Returns:
- A tuple (base_content, new_content, is_binary, status)
- base_content: The contents of the base file.
- new_content: For text files, this is empty. For binary files, this is
- the contents of the new file, since the diff output won't contain
- information to reconstruct the current file.
- is_binary: True iff the file is binary.
- status: The status of the file.
- """
-
- raise NotImplementedError(
- "abstract method -- subclass %s must override" % self.__class__)
-
-
- def GetBaseFiles(self, diff):
- """Helper that calls GetBase file for each file in the patch.
-
- Returns:
- A dictionary that maps from filename to GetBaseFile's tuple. Filenames
- are retrieved based on lines that start with "Index:" or
- "Property changes on:".
- """
- files = {}
- for line in diff.splitlines(True):
- if line.startswith('Index:') or line.startswith('Property changes on:'):
- unused, filename = line.split(':', 1)
- # On Windows if a file has property changes its filename uses '\'
- # instead of '/'.
- filename = filename.strip().replace('\\', '/')
- files[filename] = self.GetBaseFile(filename)
- return files
-
-
- def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options,
- files):
- """Uploads the base files (and if necessary, the current ones as well)."""
-
- def UploadFile(filename, file_id, content, is_binary, status, is_base):
- """Uploads a file to the server."""
- file_too_large = False
- if is_base:
- type = "base"
- else:
- type = "current"
- if len(content) > MAX_UPLOAD_SIZE:
- print ("Not uploading the %s file for %s because it's too large." %
- (type, filename))
- file_too_large = True
- content = ""
- checksum = md5.new(content).hexdigest()
- if options.verbose > 0 and not file_too_large:
- print "Uploading %s file for %s" % (type, filename)
- url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id)
- form_fields = [("filename", filename),
- ("status", status),
- ("checksum", checksum),
- ("is_binary", str(is_binary)),
- ("is_current", str(not is_base)),
- ]
- if file_too_large:
- form_fields.append(("file_too_large", "1"))
- if options.email:
- form_fields.append(("user", options.email))
- ctype, body = EncodeMultipartFormData(form_fields,
- [("data", filename, content)])
- response_body = rpc_server.Send(url, body,
- content_type=ctype)
- if not response_body.startswith("OK"):
- StatusUpdate(" --> %s" % response_body)
- sys.exit(1)
-
- patches = dict()
- [patches.setdefault(v, k) for k, v in patch_list]
- for filename in patches.keys():
- base_content, new_content, is_binary, status = files[filename]
- file_id_str = patches.get(filename)
- if file_id_str.find("nobase") != -1:
- base_content = None
- file_id_str = file_id_str[file_id_str.rfind("_") + 1:]
- file_id = int(file_id_str)
- if base_content != None:
- UploadFile(filename, file_id, base_content, is_binary, status, True)
- if new_content != None:
- UploadFile(filename, file_id, new_content, is_binary, status, False)
-
- def IsImage(self, filename):
- """Returns true if the filename has an image extension."""
- mimetype = mimetypes.guess_type(filename)[0]
- if not mimetype:
- return False
- return mimetype.startswith("image/")
-
-
-class SubversionVCS(VersionControlSystem):
- """Implementation of the VersionControlSystem interface for Subversion."""
-
- def __init__(self, options):
- super(SubversionVCS, self).__init__(options)
- if self.options.revision:
- match = re.match(r"(\d+)(:(\d+))?", self.options.revision)
- if not match:
- ErrorExit("Invalid Subversion revision %s." % self.options.revision)
- self.rev_start = match.group(1)
- self.rev_end = match.group(3)
- else:
- self.rev_start = self.rev_end = None
- # Cache output from "svn list -r REVNO dirname".
- # Keys: dirname, Values: 2-tuple (output for start rev and end rev).
- self.svnls_cache = {}
- # SVN base URL is required to fetch files deleted in an older revision.
- # Result is cached to not guess it over and over again in GetBaseFile().
- required = self.options.download_base or self.options.revision is not None
- self.svn_base = self._GuessBase(required)
-
- def GuessBase(self, required):
- """Wrapper for _GuessBase."""
- return self.svn_base
-
- def _GuessBase(self, required):
- """Returns the SVN base URL.
-
- Args:
- required: If true, exits if the url can't be guessed, otherwise None is
- returned.
- """
- info = RunShell(["svn", "info"])
- for line in info.splitlines():
- words = line.split()
- if len(words) == 2 and words[0] == "URL:":
- url = words[1]
- scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
- username, netloc = urllib.splituser(netloc)
- if username:
- logging.info("Removed username from base URL")
- if netloc.endswith("svn.python.org"):
- if netloc == "svn.python.org":
- if path.startswith("/projects/"):
- path = path[9:]
- elif netloc != "pythondev@svn.python.org":
- ErrorExit("Unrecognized Python URL: %s" % url)
- base = "http://svn.python.org/view/*checkout*%s/" % path
- logging.info("Guessed Python base = %s", base)
- elif netloc.endswith("svn.collab.net"):
- if path.startswith("/repos/"):
- path = path[6:]
- base = "http://svn.collab.net/viewvc/*checkout*%s/" % path
- logging.info("Guessed CollabNet base = %s", base)
- elif netloc.endswith(".googlecode.com"):
- path = path + "/"
- base = urlparse.urlunparse(("http", netloc, path, params,
- query, fragment))
- logging.info("Guessed Google Code base = %s", base)
- else:
- path = path + "/"
- base = urlparse.urlunparse((scheme, netloc, path, params,
- query, fragment))
- logging.info("Guessed base = %s", base)
- return base
- if required:
- ErrorExit("Can't find URL in output from svn info")
- return None
-
- def GenerateDiff(self, args):
- cmd = ["svn", "diff"]
- if self.options.revision:
- cmd += ["-r", self.options.revision]
- cmd.extend(args)
- data = RunShell(cmd)
- count = 0
- for line in data.splitlines():
- if line.startswith("Index:") or line.startswith("Property changes on:"):
- count += 1
- logging.info(line)
- if not count:
- ErrorExit("No valid patches found in output from svn diff")
- return data
-
- def _CollapseKeywords(self, content, keyword_str):
- """Collapses SVN keywords."""
- # svn cat translates keywords but svn diff doesn't. As a result of this
- # behavior patching.PatchChunks() fails with a chunk mismatch error.
- # This part was originally written by the Review Board development team
- # who had the same problem (https://reviews.reviewboard.org/r/276/).
- # Mapping of keywords to known aliases
- svn_keywords = {
- # Standard keywords
- 'Date': ['Date', 'LastChangedDate'],
- 'Revision': ['Revision', 'LastChangedRevision', 'Rev'],
- 'Author': ['Author', 'LastChangedBy'],
- 'HeadURL': ['HeadURL', 'URL'],
- 'Id': ['Id'],
-
- # Aliases
- 'LastChangedDate': ['LastChangedDate', 'Date'],
- 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'],
- 'LastChangedBy': ['LastChangedBy', 'Author'],
- 'URL': ['URL', 'HeadURL'],
- }
-
- def repl(m):
- if m.group(2):
- return "$%s::%s$" % (m.group(1), " " * len(m.group(3)))
- return "$%s$" % m.group(1)
- keywords = [keyword
- for name in keyword_str.split(" ")
- for keyword in svn_keywords.get(name, [])]
- return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content)
-
- def GetUnknownFiles(self):
- status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True)
- unknown_files = []
- for line in status.split("\n"):
- if line and line[0] == "?":
- unknown_files.append(line)
- return unknown_files
-
- def ReadFile(self, filename):
- """Returns the contents of a file."""
- file = open(filename, 'rb')
- result = ""
- try:
- result = file.read()
- finally:
- file.close()
- return result
-
- def GetStatus(self, filename):
- """Returns the status of a file."""
- if not self.options.revision:
- status = RunShell(["svn", "status", "--ignore-externals", filename])
- if not status:
- ErrorExit("svn status returned no output for %s" % filename)
- status_lines = status.splitlines()
- # If file is in a cl, the output will begin with
- # "\n--- Changelist 'cl_name':\n". See
- # https://web.archive.org/web/20090918234815/svn.collab.net/repos/svn/trunk/notes/changelist-design.txt
- if (len(status_lines) == 3 and
- not status_lines[0] and
- status_lines[1].startswith("--- Changelist")):
- status = status_lines[2]
- else:
- status = status_lines[0]
- # If we have a revision to diff against we need to run "svn list"
- # for the old and the new revision and compare the results to get
- # the correct status for a file.
- else:
- dirname, relfilename = os.path.split(filename)
- if dirname not in self.svnls_cache:
- cmd = ["svn", "list", "-r", self.rev_start, dirname or "."]
- out, returncode = RunShellWithReturnCode(cmd)
- if returncode:
- ErrorExit("Failed to get status for %s." % filename)
- old_files = out.splitlines()
- args = ["svn", "list"]
- if self.rev_end:
- args += ["-r", self.rev_end]
- cmd = args + [dirname or "."]
- out, returncode = RunShellWithReturnCode(cmd)
- if returncode:
- ErrorExit("Failed to run command %s" % cmd)
- self.svnls_cache[dirname] = (old_files, out.splitlines())
- old_files, new_files = self.svnls_cache[dirname]
- if relfilename in old_files and relfilename not in new_files:
- status = "D "
- elif relfilename in old_files and relfilename in new_files:
- status = "M "
- else:
- status = "A "
- return status
-
- def GetBaseFile(self, filename):
- status = self.GetStatus(filename)
- base_content = None
- new_content = None
-
- # If a file is copied its status will be "A +", which signifies
- # "addition-with-history". See "svn st" for more information. We need to
- # upload the original file or else diff parsing will fail if the file was
- # edited.
- if status[0] == "A" and status[3] != "+":
- # We'll need to upload the new content if we're adding a binary file
- # since diff's output won't contain it.
- mimetype = RunShell(["svn", "propget", "svn:mime-type", filename],
- silent_ok=True)
- base_content = ""
- is_binary = mimetype and not mimetype.startswith("text/")
- if is_binary and self.IsImage(filename):
- new_content = self.ReadFile(filename)
- elif (status[0] in ("M", "D", "R") or
- (status[0] == "A" and status[3] == "+") or # Copied file.
- (status[0] == " " and status[1] == "M")): # Property change.
- args = []
- if self.options.revision:
- url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
- else:
- # Don't change filename, it's needed later.
- url = filename
- args += ["-r", "BASE"]
- cmd = ["svn"] + args + ["propget", "svn:mime-type", url]
- mimetype, returncode = RunShellWithReturnCode(cmd)
- if returncode:
- # File does not exist in the requested revision.
- # Reset mimetype, it contains an error message.
- mimetype = ""
- get_base = False
- is_binary = mimetype and not mimetype.startswith("text/")
- if status[0] == " ":
- # Empty base content just to force an upload.
- base_content = ""
- elif is_binary:
- if self.IsImage(filename):
- get_base = True
- if status[0] == "M":
- if not self.rev_end:
- new_content = self.ReadFile(filename)
- else:
- url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end)
- new_content = RunShell(["svn", "cat", url],
- universal_newlines=True, silent_ok=True)
- else:
- base_content = ""
- else:
- get_base = True
-
- if get_base:
- if is_binary:
- universal_newlines = False
- else:
- universal_newlines = True
- if self.rev_start:
- # "svn cat -r REV delete_file.txt" doesn't work. cat requires
- # the full URL with "@REV" appended instead of using "-r" option.
- url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
- base_content = RunShell(["svn", "cat", url],
- universal_newlines=universal_newlines,
- silent_ok=True)
- else:
- base_content = RunShell(["svn", "cat", filename],
- universal_newlines=universal_newlines,
- silent_ok=True)
- if not is_binary:
- args = []
- if self.rev_start:
- url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start)
- else:
- url = filename
- args += ["-r", "BASE"]
- cmd = ["svn"] + args + ["propget", "svn:keywords", url]
- keywords, returncode = RunShellWithReturnCode(cmd)
- if keywords and not returncode:
- base_content = self._CollapseKeywords(base_content, keywords)
- else:
- StatusUpdate("svn status returned unexpected output: %s" % status)
- sys.exit(1)
- return base_content, new_content, is_binary, status[0:5]
-
-
-class GitVCS(VersionControlSystem):
- """Implementation of the VersionControlSystem interface for Git."""
-
- def __init__(self, options):
- super(GitVCS, self).__init__(options)
- # Map of filename -> hash of base file.
- self.base_hashes = {}
-
- def GenerateDiff(self, extra_args):
- # This is more complicated than svn's GenerateDiff because we must convert
- # the diff output to include an svn-style "Index:" line as well as record
- # the hashes of the base files, so we can upload them along with our diff.
- if self.options.revision:
- extra_args = [self.options.revision] + extra_args
- gitdiff = RunShell(["git", "diff", "--full-index"] + extra_args)
- svndiff = []
- filecount = 0
- filename = None
- for line in gitdiff.splitlines():
- match = re.match(r"diff --git a/(.*) b/.*$", line)
- if match:
- filecount += 1
- filename = match.group(1)
- svndiff.append("Index: %s\n" % filename)
- else:
- # The "index" line in a git diff looks like this (long hashes elided):
- # index 82c0d44..b2cee3f 100755
- # We want to save the left hash, as that identifies the base file.
- match = re.match(r"index (\w+)\.\.", line)
- if match:
- self.base_hashes[filename] = match.group(1)
- svndiff.append(line + "\n")
- if not filecount:
- ErrorExit("No valid patches found in output from git diff")
- return "".join(svndiff)
-
- def GetUnknownFiles(self):
- status = RunShell(["git", "ls-files", "--exclude-standard", "--others"],
- silent_ok=True)
- return status.splitlines()
-
- def GetBaseFile(self, filename):
- hash = self.base_hashes[filename]
- base_content = None
- new_content = None
- is_binary = False
- if hash == "0" * 40: # All-zero hash indicates no base file.
- status = "A"
- base_content = ""
- else:
- status = "M"
- base_content, returncode = RunShellWithReturnCode(["git", "show", hash])
- if returncode:
- ErrorExit("Got error status from 'git show %s'" % hash)
- return (base_content, new_content, is_binary, status)
-
-
-class MercurialVCS(VersionControlSystem):
- """Implementation of the VersionControlSystem interface for Mercurial."""
-
- def __init__(self, options, repo_dir):
- super(MercurialVCS, self).__init__(options)
- # Absolute path to repository (we can be in a subdir)
- self.repo_dir = os.path.normpath(repo_dir)
- # Compute the subdir
- cwd = os.path.normpath(os.getcwd())
- assert cwd.startswith(self.repo_dir)
- self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/")
- if self.options.revision:
- self.base_rev = self.options.revision
- else:
- self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip()
-
- def _GetRelPath(self, filename):
- """Get relative path of a file according to the current directory,
- given its logical path in the repo."""
- assert filename.startswith(self.subdir), filename
- return filename[len(self.subdir):].lstrip(r"\/")
-
- def GenerateDiff(self, extra_args):
- # If no file specified, restrict to the current subdir
- extra_args = extra_args or ["."]
- cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args
- data = RunShell(cmd, silent_ok=True)
- svndiff = []
- filecount = 0
- for line in data.splitlines():
- m = re.match("diff --git a/(\S+) b/(\S+)", line)
- if m:
- # Modify line to make it look like as it comes from svn diff.
- # With this modification no changes on the server side are required
- # to make upload.py work with Mercurial repos.
- # NOTE: for proper handling of moved/copied files, we have to use
- # the second filename.
- filename = m.group(2)
- svndiff.append("Index: %s" % filename)
- svndiff.append("=" * 67)
- filecount += 1
- logging.info(line)
- else:
- svndiff.append(line)
- if not filecount:
- ErrorExit("No valid patches found in output from hg diff")
- return "\n".join(svndiff) + "\n"
-
- def GetUnknownFiles(self):
- """Return a list of files unknown to the VCS."""
- args = []
- status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."],
- silent_ok=True)
- unknown_files = []
- for line in status.splitlines():
- st, fn = line.split(" ", 1)
- if st == "?":
- unknown_files.append(fn)
- return unknown_files
-
- def GetBaseFile(self, filename):
- # "hg status" and "hg cat" both take a path relative to the current subdir
- # rather than to the repo root, but "hg diff" has given us the full path
- # to the repo root.
- base_content = ""
- new_content = None
- is_binary = False
- oldrelpath = relpath = self._GetRelPath(filename)
- # "hg status -C" returns two lines for moved/copied files, one otherwise
- out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath])
- out = out.splitlines()
- # HACK: strip error message about missing file/directory if it isn't in
- # the working copy
- if out[0].startswith('%s: ' % relpath):
- out = out[1:]
- if len(out) > 1:
- # Moved/copied => considered as modified, use old filename to
- # retrieve base contents
- oldrelpath = out[1].strip()
- status = "M"
- else:
- status, _ = out[0].split(' ', 1)
- if status != "A":
- base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
- silent_ok=True)
- is_binary = "\0" in base_content # Mercurial's heuristic
- if status != "R":
- new_content = open(relpath, "rb").read()
- is_binary = is_binary or "\0" in new_content
- if is_binary and base_content:
- # Fetch again without converting newlines
- base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath],
- silent_ok=True, universal_newlines=False)
- if not is_binary or not self.IsImage(relpath):
- new_content = None
- return base_content, new_content, is_binary, status
-
-
-# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync.
-def SplitPatch(data):
- """Splits a patch into separate pieces for each file.
-
- Args:
- data: A string containing the output of svn diff.
-
- Returns:
- A list of 2-tuple (filename, text) where text is the svn diff output
- pertaining to filename.
- """
- patches = []
- filename = None
- diff = []
- for line in data.splitlines(True):
- new_filename = None
- if line.startswith('Index:'):
- unused, new_filename = line.split(':', 1)
- new_filename = new_filename.strip()
- elif line.startswith('Property changes on:'):
- unused, temp_filename = line.split(':', 1)
- # When a file is modified, paths use '/' between directories, however
- # when a property is modified '\' is used on Windows. Make them the same
- # otherwise the file shows up twice.
- temp_filename = temp_filename.strip().replace('\\', '/')
- if temp_filename != filename:
- # File has property changes but no modifications, create a new diff.
- new_filename = temp_filename
- if new_filename:
- if filename and diff:
- patches.append((filename, ''.join(diff)))
- filename = new_filename
- diff = [line]
- continue
- if diff is not None:
- diff.append(line)
- if filename and diff:
- patches.append((filename, ''.join(diff)))
- return patches
-
-
-def UploadSeparatePatches(issue, rpc_server, patchset, data, options):
- """Uploads a separate patch for each file in the diff output.
-
- Returns a list of [patch_key, filename] for each file.
- """
- patches = SplitPatch(data)
- rv = []
- for patch in patches:
- if len(patch[1]) > MAX_UPLOAD_SIZE:
- print ("Not uploading the patch for " + patch[0] +
- " because the file is too large.")
- continue
- form_fields = [("filename", patch[0])]
- if not options.download_base:
- form_fields.append(("content_upload", "1"))
- files = [("data", "data.diff", patch[1])]
- ctype, body = EncodeMultipartFormData(form_fields, files)
- url = "/%d/upload_patch/%d" % (int(issue), int(patchset))
- print "Uploading patch for " + patch[0]
- response_body = rpc_server.Send(url, body, content_type=ctype)
- lines = response_body.splitlines()
- if not lines or lines[0] != "OK":
- StatusUpdate(" --> %s" % response_body)
- sys.exit(1)
- rv.append([lines[1], patch[0]])
- return rv
-
-
-def GuessVCS(options):
- """Helper to guess the version control system.
-
- This examines the current directory, guesses which VersionControlSystem
- we're using, and returns an instance of the appropriate class. Exit with an
- error if we can't figure it out.
-
- Returns:
- A VersionControlSystem instance. Exits if the VCS can't be guessed.
- """
- # Mercurial has a command to get the base directory of a repository
- # Try running it, but don't die if we don't have hg installed.
- # NOTE: we try Mercurial first as it can sit on top of an SVN working copy.
- try:
- out, returncode = RunShellWithReturnCode(["hg", "root"])
- if returncode == 0:
- return MercurialVCS(options, out.strip())
- except OSError, (errno, message):
- if errno != 2: # ENOENT -- they don't have hg installed.
- raise
-
- # Subversion has a .svn in all working directories.
- if os.path.isdir('.svn'):
- logging.info("Guessed VCS = Subversion")
- return SubversionVCS(options)
-
- # Git has a command to test if you're in a git tree.
- # Try running it, but don't die if we don't have git installed.
- try:
- out, returncode = RunShellWithReturnCode(["git", "rev-parse",
- "--is-inside-work-tree"])
- if returncode == 0:
- return GitVCS(options)
- except OSError, (errno, message):
- if errno != 2: # ENOENT -- they don't have git installed.
- raise
-
- ErrorExit(("Could not guess version control system. "
- "Are you in a working copy directory?"))
-
-
-def RealMain(argv, data=None):
- """The real main function.
-
- Args:
- argv: Command line arguments.
- data: Diff contents. If None (default) the diff is generated by
- the VersionControlSystem implementation returned by GuessVCS().
-
- Returns:
- A 2-tuple (issue id, patchset id).
- The patchset id is None if the base files are not uploaded by this
- script (applies only to SVN checkouts).
- """
- logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:"
- "%(lineno)s %(message)s "))
- os.environ['LC_ALL'] = 'C'
- options, args = parser.parse_args(argv[1:])
- global verbosity
- verbosity = options.verbose
- if verbosity >= 3:
- logging.getLogger().setLevel(logging.DEBUG)
- elif verbosity >= 2:
- logging.getLogger().setLevel(logging.INFO)
- vcs = GuessVCS(options)
- if isinstance(vcs, SubversionVCS):
- # base field is only allowed for Subversion.
- # Note: Fetching base files may become deprecated in future releases.
- base = vcs.GuessBase(options.download_base)
- else:
- base = None
- if not base and options.download_base:
- options.download_base = True
- logging.info("Enabled upload of base file")
- if not options.assume_yes:
- vcs.CheckForUnknownFiles()
- if data is None:
- data = vcs.GenerateDiff(args)
- files = vcs.GetBaseFiles(data)
- if verbosity >= 1:
- print "Upload server:", options.server, "(change with -s/--server)"
- if options.issue:
- prompt = "Message describing this patch set: "
- else:
- prompt = "New issue subject: "
- message = options.message or raw_input(prompt).strip()
- if not message:
- ErrorExit("A non-empty message is required")
- rpc_server = GetRpcServer(options)
- form_fields = [("subject", message)]
- if base:
- form_fields.append(("base", base))
- if options.issue:
- form_fields.append(("issue", str(options.issue)))
- if options.email:
- form_fields.append(("user", options.email))
- if options.reviewers:
- for reviewer in options.reviewers.split(','):
- if "@" in reviewer and not reviewer.split("@")[1].count(".") == 1:
- ErrorExit("Invalid email address: %s" % reviewer)
- form_fields.append(("reviewers", options.reviewers))
- if options.cc:
- for cc in options.cc.split(','):
- if "@" in cc and not cc.split("@")[1].count(".") == 1:
- ErrorExit("Invalid email address: %s" % cc)
- form_fields.append(("cc", options.cc))
- description = options.description
- if options.description_file:
- if options.description:
- ErrorExit("Can't specify description and description_file")
- file = open(options.description_file, 'r')
- description = file.read()
- file.close()
- if description:
- form_fields.append(("description", description))
- # Send a hash of all the base file so the server can determine if a copy
- # already exists in an earlier patchset.
- base_hashes = ""
- for file, info in files.iteritems():
- if not info[0] is None:
- checksum = md5.new(info[0]).hexdigest()
- if base_hashes:
- base_hashes += "|"
- base_hashes += checksum + ":" + file
- form_fields.append(("base_hashes", base_hashes))
- # If we're uploading base files, don't send the email before the uploads, so
- # that it contains the file status.
- if options.send_mail and options.download_base:
- form_fields.append(("send_mail", "1"))
- if not options.download_base:
- form_fields.append(("content_upload", "1"))
- if len(data) > MAX_UPLOAD_SIZE:
- print "Patch is large, so uploading file patches separately."
- uploaded_diff_file = []
- form_fields.append(("separate_patches", "1"))
- else:
- uploaded_diff_file = [("data", "data.diff", data)]
- ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file)
- response_body = rpc_server.Send("/upload", body, content_type=ctype)
- patchset = None
- if not options.download_base or not uploaded_diff_file:
- lines = response_body.splitlines()
- if len(lines) >= 2:
- msg = lines[0]
- patchset = lines[1].strip()
- patches = [x.split(" ", 1) for x in lines[2:]]
- else:
- msg = response_body
- else:
- msg = response_body
- StatusUpdate(msg)
- if not response_body.startswith("Issue created.") and \
- not response_body.startswith("Issue updated."):
- sys.exit(0)
- issue = msg[msg.rfind("/")+1:]
-
- if not uploaded_diff_file:
- result = UploadSeparatePatches(issue, rpc_server, patchset, data, options)
- if not options.download_base:
- patches = result
-
- if not options.download_base:
- vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files)
- if options.send_mail:
- rpc_server.Send("/" + issue + "/mail", payload="")
- return issue, patchset
-
-
-def main():
- try:
- RealMain(sys.argv)
- except KeyboardInterrupt:
- print
- StatusUpdate("Interrupted.")
- sys.exit(1)
-
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""upload_gtest.py v0.1.0 -- uploads a Google Test patch for review.
-
-This simple wrapper passes all command line flags and
---cc=googletestframework@googlegroups.com to upload.py.
-
-USAGE: upload_gtest.py [options for upload.py]
-"""
-
-__author__ = 'wan@google.com (Zhanyong Wan)'
-
-import os
-import sys
-
-CC_FLAG = '--cc='
-GTEST_GROUP = 'googletestframework@googlegroups.com'
-
-
-def main():
- # Finds the path to upload.py, assuming it is in the same directory
- # as this file.
- my_dir = os.path.dirname(os.path.abspath(__file__))
- upload_py_path = os.path.join(my_dir, 'upload.py')
-
- # Adds Google Test discussion group to the cc line if it's not there
- # already.
- upload_py_argv = [upload_py_path]
- found_cc_flag = False
- for arg in sys.argv[1:]:
- if arg.startswith(CC_FLAG):
- found_cc_flag = True
- cc_line = arg[len(CC_FLAG):]
- cc_list = [addr for addr in cc_line.split(',') if addr]
- if GTEST_GROUP not in cc_list:
- cc_list.append(GTEST_GROUP)
- upload_py_argv.append(CC_FLAG + ','.join(cc_list))
- else:
- upload_py_argv.append(arg)
-
- if not found_cc_flag:
- upload_py_argv.append(CC_FLAG + GTEST_GROUP)
-
- # Invokes upload.py with the modified command line flags.
- os.execv(upload_py_path, upload_py_argv)
-
-
-if __name__ == '__main__':
- main()
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Google C++ Testing and Mocking Framework (Google Test)
-//
-// Sometimes it's desirable to build Google Test by compiling a single file.
-// This file serves this purpose.
-
-// This line ensures that gtest.h can be compiled on its own, even
-// when it's fused.
-#include "gtest/gtest.h"
-
-// The following lines pull in the real gtest *.cc files.
-#include "src/gtest.cc"
-#include "src/gtest-death-test.cc"
-#include "src/gtest-filepath.cc"
-#include "src/gtest-matchers.cc"
-#include "src/gtest-port.cc"
-#include "src/gtest-printers.cc"
-#include "src/gtest-test-part.cc"
-#include "src/gtest-typed-test.cc"
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// This file implements death tests.
-
-#include "gtest/gtest-death-test.h"
-
-#include <utility>
-
-#include "gtest/internal/gtest-port.h"
-#include "gtest/internal/custom/gtest.h"
-
-#if GTEST_HAS_DEATH_TEST
-
-# if GTEST_OS_MAC
-# include <crt_externs.h>
-# endif // GTEST_OS_MAC
-
-# include <errno.h>
-# include <fcntl.h>
-# include <limits.h>
-
-# if GTEST_OS_LINUX
-# include <signal.h>
-# endif // GTEST_OS_LINUX
-
-# include <stdarg.h>
-
-# if GTEST_OS_WINDOWS
-# include <windows.h>
-# else
-# include <sys/mman.h>
-# include <sys/wait.h>
-# endif // GTEST_OS_WINDOWS
-
-# if GTEST_OS_QNX
-# include <spawn.h>
-# endif // GTEST_OS_QNX
-
-# if GTEST_OS_FUCHSIA
-# include <lib/fdio/fd.h>
-# include <lib/fdio/io.h>
-# include <lib/fdio/spawn.h>
-# include <lib/zx/channel.h>
-# include <lib/zx/port.h>
-# include <lib/zx/process.h>
-# include <lib/zx/socket.h>
-# include <zircon/processargs.h>
-# include <zircon/syscalls.h>
-# include <zircon/syscalls/policy.h>
-# include <zircon/syscalls/port.h>
-# endif // GTEST_OS_FUCHSIA
-
-#endif // GTEST_HAS_DEATH_TEST
-
-#include "gtest/gtest-message.h"
-#include "gtest/internal/gtest-string.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-
-// Constants.
-
-// The default death test style.
-//
-// This is defined in internal/gtest-port.h as "fast", but can be overridden by
-// a definition in internal/custom/gtest-port.h. The recommended value, which is
-// used internally at Google, is "threadsafe".
-static const char kDefaultDeathTestStyle[] = GTEST_DEFAULT_DEATH_TEST_STYLE;
-
-GTEST_DEFINE_string_(
- death_test_style,
- internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
- "Indicates how to run a death test in a forked child process: "
- "\"threadsafe\" (child process re-executes the test binary "
- "from the beginning, running only the specific death test) or "
- "\"fast\" (child process runs the death test immediately "
- "after forking).");
-
-GTEST_DEFINE_bool_(
- death_test_use_fork,
- internal::BoolFromGTestEnv("death_test_use_fork", false),
- "Instructs to use fork()/_exit() instead of clone() in death tests. "
- "Ignored and always uses fork() on POSIX systems where clone() is not "
- "implemented. Useful when running under valgrind or similar tools if "
- "those do not support clone(). Valgrind 3.3.1 will just fail if "
- "it sees an unsupported combination of clone() flags. "
- "It is not recommended to use this flag w/o valgrind though it will "
- "work in 99% of the cases. Once valgrind is fixed, this flag will "
- "most likely be removed.");
-
-namespace internal {
-GTEST_DEFINE_string_(
- internal_run_death_test, "",
- "Indicates the file, line number, temporal index of "
- "the single death test to run, and a file descriptor to "
- "which a success code may be sent, all separated by "
- "the '|' characters. This flag is specified if and only if the "
- "current process is a sub-process launched for running a thread-safe "
- "death test. FOR INTERNAL USE ONLY.");
-} // namespace internal
-
-#if GTEST_HAS_DEATH_TEST
-
-namespace internal {
-
-// Valid only for fast death tests. Indicates the code is running in the
-// child process of a fast style death test.
-# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
-static bool g_in_fast_death_test_child = false;
-# endif
-
-// Returns a Boolean value indicating whether the caller is currently
-// executing in the context of the death test child process. Tools such as
-// Valgrind heap checkers may need this to modify their behavior in death
-// tests. IMPORTANT: This is an internal utility. Using it may break the
-// implementation of death tests. User code MUST NOT use it.
-bool InDeathTestChild() {
-# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-
- // On Windows and Fuchsia, death tests are thread-safe regardless of the value
- // of the death_test_style flag.
- return !GTEST_FLAG(internal_run_death_test).empty();
-
-# else
-
- if (GTEST_FLAG(death_test_style) == "threadsafe")
- return !GTEST_FLAG(internal_run_death_test).empty();
- else
- return g_in_fast_death_test_child;
-#endif
-}
-
-} // namespace internal
-
-// ExitedWithCode constructor.
-ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
-}
-
-// ExitedWithCode function-call operator.
-bool ExitedWithCode::operator()(int exit_status) const {
-# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-
- return exit_status == exit_code_;
-
-# else
-
- return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
-
-# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-}
-
-# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
-// KilledBySignal constructor.
-KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
-}
-
-// KilledBySignal function-call operator.
-bool KilledBySignal::operator()(int exit_status) const {
-# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
- {
- bool result;
- if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
- return result;
- }
- }
-# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
- return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
-}
-# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
-
-namespace internal {
-
-// Utilities needed for death tests.
-
-// Generates a textual description of a given exit code, in the format
-// specified by wait(2).
-static std::string ExitSummary(int exit_code) {
- Message m;
-
-# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-
- m << "Exited with exit status " << exit_code;
-
-# else
-
- if (WIFEXITED(exit_code)) {
- m << "Exited with exit status " << WEXITSTATUS(exit_code);
- } else if (WIFSIGNALED(exit_code)) {
- m << "Terminated by signal " << WTERMSIG(exit_code);
- }
-# ifdef WCOREDUMP
- if (WCOREDUMP(exit_code)) {
- m << " (core dumped)";
- }
-# endif
-# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-
- return m.GetString();
-}
-
-// Returns true if exit_status describes a process that was terminated
-// by a signal, or exited normally with a nonzero exit code.
-bool ExitedUnsuccessfully(int exit_status) {
- return !ExitedWithCode(0)(exit_status);
-}
-
-# if !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
-// Generates a textual failure message when a death test finds more than
-// one thread running, or cannot determine the number of threads, prior
-// to executing the given statement. It is the responsibility of the
-// caller not to pass a thread_count of 1.
-static std::string DeathTestThreadWarning(size_t thread_count) {
- Message msg;
- msg << "Death tests use fork(), which is unsafe particularly"
- << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
- if (thread_count == 0) {
- msg << "couldn't detect the number of threads.";
- } else {
- msg << "detected " << thread_count << " threads.";
- }
- msg << " See "
- "https://github.com/google/googletest/blob/master/googletest/docs/"
- "advanced.md#death-tests-and-threads"
- << " for more explanation and suggested solutions, especially if"
- << " this is the last message you see before your test times out.";
- return msg.GetString();
-}
-# endif // !GTEST_OS_WINDOWS && !GTEST_OS_FUCHSIA
-
-// Flag characters for reporting a death test that did not die.
-static const char kDeathTestLived = 'L';
-static const char kDeathTestReturned = 'R';
-static const char kDeathTestThrew = 'T';
-static const char kDeathTestInternalError = 'I';
-
-#if GTEST_OS_FUCHSIA
-
-// File descriptor used for the pipe in the child process.
-static const int kFuchsiaReadPipeFd = 3;
-
-#endif
-
-// An enumeration describing all of the possible ways that a death test can
-// conclude. DIED means that the process died while executing the test
-// code; LIVED means that process lived beyond the end of the test code;
-// RETURNED means that the test statement attempted to execute a return
-// statement, which is not allowed; THREW means that the test statement
-// returned control by throwing an exception. IN_PROGRESS means the test
-// has not yet concluded.
-enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
-
-// Routine for aborting the program which is safe to call from an
-// exec-style death test child process, in which case the error
-// message is propagated back to the parent process. Otherwise, the
-// message is simply printed to stderr. In either case, the program
-// then exits with status 1.
-static void DeathTestAbort(const std::string& message) {
- // On a POSIX system, this function may be called from a threadsafe-style
- // death test child process, which operates on a very small stack. Use
- // the heap for any additional non-minuscule memory requirements.
- const InternalRunDeathTestFlag* const flag =
- GetUnitTestImpl()->internal_run_death_test_flag();
- if (flag != nullptr) {
- FILE* parent = posix::FDOpen(flag->write_fd(), "w");
- fputc(kDeathTestInternalError, parent);
- fprintf(parent, "%s", message.c_str());
- fflush(parent);
- _exit(1);
- } else {
- fprintf(stderr, "%s", message.c_str());
- fflush(stderr);
- posix::Abort();
- }
-}
-
-// A replacement for CHECK that calls DeathTestAbort if the assertion
-// fails.
-# define GTEST_DEATH_TEST_CHECK_(expression) \
- do { \
- if (!::testing::internal::IsTrue(expression)) { \
- DeathTestAbort( \
- ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
- + ::testing::internal::StreamableToString(__LINE__) + ": " \
- + #expression); \
- } \
- } while (::testing::internal::AlwaysFalse())
-
-// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
-// evaluating any system call that fulfills two conditions: it must return
-// -1 on failure, and set errno to EINTR when it is interrupted and
-// should be tried again. The macro expands to a loop that repeatedly
-// evaluates the expression as long as it evaluates to -1 and sets
-// errno to EINTR. If the expression evaluates to -1 but errno is
-// something other than EINTR, DeathTestAbort is called.
-# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
- do { \
- int gtest_retval; \
- do { \
- gtest_retval = (expression); \
- } while (gtest_retval == -1 && errno == EINTR); \
- if (gtest_retval == -1) { \
- DeathTestAbort( \
- ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
- + ::testing::internal::StreamableToString(__LINE__) + ": " \
- + #expression + " != -1"); \
- } \
- } while (::testing::internal::AlwaysFalse())
-
-// Returns the message describing the last system error in errno.
-std::string GetLastErrnoDescription() {
- return errno == 0 ? "" : posix::StrError(errno);
-}
-
-// This is called from a death test parent process to read a failure
-// message from the death test child process and log it with the FATAL
-// severity. On Windows, the message is read from a pipe handle. On other
-// platforms, it is read from a file descriptor.
-static void FailFromInternalError(int fd) {
- Message error;
- char buffer[256];
- int num_read;
-
- do {
- while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
- buffer[num_read] = '\0';
- error << buffer;
- }
- } while (num_read == -1 && errno == EINTR);
-
- if (num_read == 0) {
- GTEST_LOG_(FATAL) << error.GetString();
- } else {
- const int last_error = errno;
- GTEST_LOG_(FATAL) << "Error while reading death test internal: "
- << GetLastErrnoDescription() << " [" << last_error << "]";
- }
-}
-
-// Death test constructor. Increments the running death test count
-// for the current test.
-DeathTest::DeathTest() {
- TestInfo* const info = GetUnitTestImpl()->current_test_info();
- if (info == nullptr) {
- DeathTestAbort("Cannot run a death test outside of a TEST or "
- "TEST_F construct");
- }
-}
-
-// Creates and returns a death test by dispatching to the current
-// death test factory.
-bool DeathTest::Create(const char* statement,
- Matcher<const std::string&> matcher, const char* file,
- int line, DeathTest** test) {
- return GetUnitTestImpl()->death_test_factory()->Create(
- statement, std::move(matcher), file, line, test);
-}
-
-const char* DeathTest::LastMessage() {
- return last_death_test_message_.c_str();
-}
-
-void DeathTest::set_last_death_test_message(const std::string& message) {
- last_death_test_message_ = message;
-}
-
-std::string DeathTest::last_death_test_message_;
-
-// Provides cross platform implementation for some death functionality.
-class DeathTestImpl : public DeathTest {
- protected:
- DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
- : statement_(a_statement),
- matcher_(std::move(matcher)),
- spawned_(false),
- status_(-1),
- outcome_(IN_PROGRESS),
- read_fd_(-1),
- write_fd_(-1) {}
-
- // read_fd_ is expected to be closed and cleared by a derived class.
- ~DeathTestImpl() override { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
-
- void Abort(AbortReason reason) override;
- bool Passed(bool status_ok) override;
-
- const char* statement() const { return statement_; }
- bool spawned() const { return spawned_; }
- void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
- int status() const { return status_; }
- void set_status(int a_status) { status_ = a_status; }
- DeathTestOutcome outcome() const { return outcome_; }
- void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
- int read_fd() const { return read_fd_; }
- void set_read_fd(int fd) { read_fd_ = fd; }
- int write_fd() const { return write_fd_; }
- void set_write_fd(int fd) { write_fd_ = fd; }
-
- // Called in the parent process only. Reads the result code of the death
- // test child process via a pipe, interprets it to set the outcome_
- // member, and closes read_fd_. Outputs diagnostics and terminates in
- // case of unexpected codes.
- void ReadAndInterpretStatusByte();
-
- // Returns stderr output from the child process.
- virtual std::string GetErrorLogs();
-
- private:
- // The textual content of the code this object is testing. This class
- // doesn't own this string and should not attempt to delete it.
- const char* const statement_;
- // A matcher that's expected to match the stderr output by the child process.
- Matcher<const std::string&> matcher_;
- // True if the death test child process has been successfully spawned.
- bool spawned_;
- // The exit status of the child process.
- int status_;
- // How the death test concluded.
- DeathTestOutcome outcome_;
- // Descriptor to the read end of the pipe to the child process. It is
- // always -1 in the child process. The child keeps its write end of the
- // pipe in write_fd_.
- int read_fd_;
- // Descriptor to the child's write end of the pipe to the parent process.
- // It is always -1 in the parent process. The parent keeps its end of the
- // pipe in read_fd_.
- int write_fd_;
-};
-
-// Called in the parent process only. Reads the result code of the death
-// test child process via a pipe, interprets it to set the outcome_
-// member, and closes read_fd_. Outputs diagnostics and terminates in
-// case of unexpected codes.
-void DeathTestImpl::ReadAndInterpretStatusByte() {
- char flag;
- int bytes_read;
-
- // The read() here blocks until data is available (signifying the
- // failure of the death test) or until the pipe is closed (signifying
- // its success), so it's okay to call this in the parent before
- // the child process has exited.
- do {
- bytes_read = posix::Read(read_fd(), &flag, 1);
- } while (bytes_read == -1 && errno == EINTR);
-
- if (bytes_read == 0) {
- set_outcome(DIED);
- } else if (bytes_read == 1) {
- switch (flag) {
- case kDeathTestReturned:
- set_outcome(RETURNED);
- break;
- case kDeathTestThrew:
- set_outcome(THREW);
- break;
- case kDeathTestLived:
- set_outcome(LIVED);
- break;
- case kDeathTestInternalError:
- FailFromInternalError(read_fd()); // Does not return.
- break;
- default:
- GTEST_LOG_(FATAL) << "Death test child process reported "
- << "unexpected status byte ("
- << static_cast<unsigned int>(flag) << ")";
- }
- } else {
- GTEST_LOG_(FATAL) << "Read from death test child process failed: "
- << GetLastErrnoDescription();
- }
- GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
- set_read_fd(-1);
-}
-
-std::string DeathTestImpl::GetErrorLogs() {
- return GetCapturedStderr();
-}
-
-// Signals that the death test code which should have exited, didn't.
-// Should be called only in a death test child process.
-// Writes a status byte to the child's status file descriptor, then
-// calls _exit(1).
-void DeathTestImpl::Abort(AbortReason reason) {
- // The parent process considers the death test to be a failure if
- // it finds any data in our pipe. So, here we write a single flag byte
- // to the pipe, then exit.
- const char status_ch =
- reason == TEST_DID_NOT_DIE ? kDeathTestLived :
- reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
-
- GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
- // We are leaking the descriptor here because on some platforms (i.e.,
- // when built as Windows DLL), destructors of global objects will still
- // run after calling _exit(). On such systems, write_fd_ will be
- // indirectly closed from the destructor of UnitTestImpl, causing double
- // close if it is also closed here. On debug configurations, double close
- // may assert. As there are no in-process buffers to flush here, we are
- // relying on the OS to close the descriptor after the process terminates
- // when the destructors are not run.
- _exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
-}
-
-// Returns an indented copy of stderr output for a death test.
-// This makes distinguishing death test output lines from regular log lines
-// much easier.
-static ::std::string FormatDeathTestOutput(const ::std::string& output) {
- ::std::string ret;
- for (size_t at = 0; ; ) {
- const size_t line_end = output.find('\n', at);
- ret += "[ DEATH ] ";
- if (line_end == ::std::string::npos) {
- ret += output.substr(at);
- break;
- }
- ret += output.substr(at, line_end + 1 - at);
- at = line_end + 1;
- }
- return ret;
-}
-
-// Assesses the success or failure of a death test, using both private
-// members which have previously been set, and one argument:
-//
-// Private data members:
-// outcome: An enumeration describing how the death test
-// concluded: DIED, LIVED, THREW, or RETURNED. The death test
-// fails in the latter three cases.
-// status: The exit status of the child process. On *nix, it is in the
-// in the format specified by wait(2). On Windows, this is the
-// value supplied to the ExitProcess() API or a numeric code
-// of the exception that terminated the program.
-// matcher_: A matcher that's expected to match the stderr output by the child
-// process.
-//
-// Argument:
-// status_ok: true if exit_status is acceptable in the context of
-// this particular death test, which fails if it is false
-//
-// Returns true if and only if all of the above conditions are met. Otherwise,
-// the first failing condition, in the order given above, is the one that is
-// reported. Also sets the last death test message string.
-bool DeathTestImpl::Passed(bool status_ok) {
- if (!spawned())
- return false;
-
- const std::string error_message = GetErrorLogs();
-
- bool success = false;
- Message buffer;
-
- buffer << "Death test: " << statement() << "\n";
- switch (outcome()) {
- case LIVED:
- buffer << " Result: failed to die.\n"
- << " Error msg:\n" << FormatDeathTestOutput(error_message);
- break;
- case THREW:
- buffer << " Result: threw an exception.\n"
- << " Error msg:\n" << FormatDeathTestOutput(error_message);
- break;
- case RETURNED:
- buffer << " Result: illegal return in test statement.\n"
- << " Error msg:\n" << FormatDeathTestOutput(error_message);
- break;
- case DIED:
- if (status_ok) {
- if (matcher_.Matches(error_message)) {
- success = true;
- } else {
- std::ostringstream stream;
- matcher_.DescribeTo(&stream);
- buffer << " Result: died but not with expected error.\n"
- << " Expected: " << stream.str() << "\n"
- << "Actual msg:\n"
- << FormatDeathTestOutput(error_message);
- }
- } else {
- buffer << " Result: died but not with expected exit code:\n"
- << " " << ExitSummary(status()) << "\n"
- << "Actual msg:\n" << FormatDeathTestOutput(error_message);
- }
- break;
- case IN_PROGRESS:
- default:
- GTEST_LOG_(FATAL)
- << "DeathTest::Passed somehow called before conclusion of test";
- }
-
- DeathTest::set_last_death_test_message(buffer.GetString());
- return success;
-}
-
-# if GTEST_OS_WINDOWS
-// WindowsDeathTest implements death tests on Windows. Due to the
-// specifics of starting new processes on Windows, death tests there are
-// always threadsafe, and Google Test considers the
-// --gtest_death_test_style=fast setting to be equivalent to
-// --gtest_death_test_style=threadsafe there.
-//
-// A few implementation notes: Like the Linux version, the Windows
-// implementation uses pipes for child-to-parent communication. But due to
-// the specifics of pipes on Windows, some extra steps are required:
-//
-// 1. The parent creates a communication pipe and stores handles to both
-// ends of it.
-// 2. The parent starts the child and provides it with the information
-// necessary to acquire the handle to the write end of the pipe.
-// 3. The child acquires the write end of the pipe and signals the parent
-// using a Windows event.
-// 4. Now the parent can release the write end of the pipe on its side. If
-// this is done before step 3, the object's reference count goes down to
-// 0 and it is destroyed, preventing the child from acquiring it. The
-// parent now has to release it, or read operations on the read end of
-// the pipe will not return when the child terminates.
-// 5. The parent reads child's output through the pipe (outcome code and
-// any possible error messages) from the pipe, and its stderr and then
-// determines whether to fail the test.
-//
-// Note: to distinguish Win32 API calls from the local method and function
-// calls, the former are explicitly resolved in the global namespace.
-//
-class WindowsDeathTest : public DeathTestImpl {
- public:
- WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
- const char* file, int line)
- : DeathTestImpl(a_statement, std::move(matcher)),
- file_(file),
- line_(line) {}
-
- // All of these virtual functions are inherited from DeathTest.
- virtual int Wait();
- virtual TestRole AssumeRole();
-
- private:
- // The name of the file in which the death test is located.
- const char* const file_;
- // The line number on which the death test is located.
- const int line_;
- // Handle to the write end of the pipe to the child process.
- AutoHandle write_handle_;
- // Child process handle.
- AutoHandle child_handle_;
- // Event the child process uses to signal the parent that it has
- // acquired the handle to the write end of the pipe. After seeing this
- // event the parent can release its own handles to make sure its
- // ReadFile() calls return when the child terminates.
- AutoHandle event_handle_;
-};
-
-// Waits for the child in a death test to exit, returning its exit
-// status, or 0 if no child process exists. As a side effect, sets the
-// outcome data member.
-int WindowsDeathTest::Wait() {
- if (!spawned())
- return 0;
-
- // Wait until the child either signals that it has acquired the write end
- // of the pipe or it dies.
- const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
- switch (::WaitForMultipleObjects(2,
- wait_handles,
- FALSE, // Waits for any of the handles.
- INFINITE)) {
- case WAIT_OBJECT_0:
- case WAIT_OBJECT_0 + 1:
- break;
- default:
- GTEST_DEATH_TEST_CHECK_(false); // Should not get here.
- }
-
- // The child has acquired the write end of the pipe or exited.
- // We release the handle on our side and continue.
- write_handle_.Reset();
- event_handle_.Reset();
-
- ReadAndInterpretStatusByte();
-
- // Waits for the child process to exit if it haven't already. This
- // returns immediately if the child has already exited, regardless of
- // whether previous calls to WaitForMultipleObjects synchronized on this
- // handle or not.
- GTEST_DEATH_TEST_CHECK_(
- WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
- INFINITE));
- DWORD status_code;
- GTEST_DEATH_TEST_CHECK_(
- ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
- child_handle_.Reset();
- set_status(static_cast<int>(status_code));
- return status();
-}
-
-// The AssumeRole process for a Windows death test. It creates a child
-// process with the same executable as the current process to run the
-// death test. The child process is given the --gtest_filter and
-// --gtest_internal_run_death_test flags such that it knows to run the
-// current death test only.
-DeathTest::TestRole WindowsDeathTest::AssumeRole() {
- const UnitTestImpl* const impl = GetUnitTestImpl();
- const InternalRunDeathTestFlag* const flag =
- impl->internal_run_death_test_flag();
- const TestInfo* const info = impl->current_test_info();
- const int death_test_index = info->result()->death_test_count();
-
- if (flag != nullptr) {
- // ParseInternalRunDeathTestFlag() has performed all the necessary
- // processing.
- set_write_fd(flag->write_fd());
- return EXECUTE_TEST;
- }
-
- // WindowsDeathTest uses an anonymous pipe to communicate results of
- // a death test.
- SECURITY_ATTRIBUTES handles_are_inheritable = {sizeof(SECURITY_ATTRIBUTES),
- nullptr, TRUE};
- HANDLE read_handle, write_handle;
- GTEST_DEATH_TEST_CHECK_(
- ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
- 0) // Default buffer size.
- != FALSE);
- set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
- O_RDONLY));
- write_handle_.Reset(write_handle);
- event_handle_.Reset(::CreateEvent(
- &handles_are_inheritable,
- TRUE, // The event will automatically reset to non-signaled state.
- FALSE, // The initial state is non-signalled.
- nullptr)); // The even is unnamed.
- GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != nullptr);
- const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
- kFilterFlag + "=" + info->test_suite_name() +
- "." + info->name();
- const std::string internal_flag =
- std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
- "=" + file_ + "|" + StreamableToString(line_) + "|" +
- StreamableToString(death_test_index) + "|" +
- StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
- // size_t has the same width as pointers on both 32-bit and 64-bit
- // Windows platforms.
- // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
- "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
- "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
-
- char executable_path[_MAX_PATH + 1]; // NOLINT
- GTEST_DEATH_TEST_CHECK_(_MAX_PATH + 1 != ::GetModuleFileNameA(nullptr,
- executable_path,
- _MAX_PATH));
-
- std::string command_line =
- std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
- internal_flag + "\"";
-
- DeathTest::set_last_death_test_message("");
-
- CaptureStderr();
- // Flush the log buffers since the log streams are shared with the child.
- FlushInfoLog();
-
- // The child process will share the standard handles with the parent.
- STARTUPINFOA startup_info;
- memset(&startup_info, 0, sizeof(STARTUPINFO));
- startup_info.dwFlags = STARTF_USESTDHANDLES;
- startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
- startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
- startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
-
- PROCESS_INFORMATION process_info;
- GTEST_DEATH_TEST_CHECK_(
- ::CreateProcessA(
- executable_path, const_cast<char*>(command_line.c_str()),
- nullptr, // Retuned process handle is not inheritable.
- nullptr, // Retuned thread handle is not inheritable.
- TRUE, // Child inherits all inheritable handles (for write_handle_).
- 0x0, // Default creation flags.
- nullptr, // Inherit the parent's environment.
- UnitTest::GetInstance()->original_working_dir(), &startup_info,
- &process_info) != FALSE);
- child_handle_.Reset(process_info.hProcess);
- ::CloseHandle(process_info.hThread);
- set_spawned(true);
- return OVERSEE_TEST;
-}
-
-# elif GTEST_OS_FUCHSIA
-
-class FuchsiaDeathTest : public DeathTestImpl {
- public:
- FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
- const char* file, int line)
- : DeathTestImpl(a_statement, std::move(matcher)),
- file_(file),
- line_(line) {}
-
- // All of these virtual functions are inherited from DeathTest.
- int Wait() override;
- TestRole AssumeRole() override;
- std::string GetErrorLogs() override;
-
- private:
- // The name of the file in which the death test is located.
- const char* const file_;
- // The line number on which the death test is located.
- const int line_;
- // The stderr data captured by the child process.
- std::string captured_stderr_;
-
- zx::process child_process_;
- zx::channel exception_channel_;
- zx::socket stderr_socket_;
-};
-
-// Utility class for accumulating command-line arguments.
-class Arguments {
- public:
- Arguments() { args_.push_back(nullptr); }
-
- ~Arguments() {
- for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
- ++i) {
- free(*i);
- }
- }
- void AddArgument(const char* argument) {
- args_.insert(args_.end() - 1, posix::StrDup(argument));
- }
-
- template <typename Str>
- void AddArguments(const ::std::vector<Str>& arguments) {
- for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
- i != arguments.end();
- ++i) {
- args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
- }
- }
- char* const* Argv() {
- return &args_[0];
- }
-
- int size() {
- return args_.size() - 1;
- }
-
- private:
- std::vector<char*> args_;
-};
-
-// Waits for the child in a death test to exit, returning its exit
-// status, or 0 if no child process exists. As a side effect, sets the
-// outcome data member.
-int FuchsiaDeathTest::Wait() {
- const int kProcessKey = 0;
- const int kSocketKey = 1;
- const int kExceptionKey = 2;
-
- if (!spawned())
- return 0;
-
- // Create a port to wait for socket/task/exception events.
- zx_status_t status_zx;
- zx::port port;
- status_zx = zx::port::create(0, &port);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- // Register to wait for the child process to terminate.
- status_zx = child_process_.wait_async(
- port, kProcessKey, ZX_PROCESS_TERMINATED, ZX_WAIT_ASYNC_ONCE);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- // Register to wait for the socket to be readable or closed.
- status_zx = stderr_socket_.wait_async(
- port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
- ZX_WAIT_ASYNC_ONCE);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- // Register to wait for an exception.
- status_zx = exception_channel_.wait_async(
- port, kExceptionKey, ZX_CHANNEL_READABLE, ZX_WAIT_ASYNC_ONCE);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- bool process_terminated = false;
- bool socket_closed = false;
- do {
- zx_port_packet_t packet = {};
- status_zx = port.wait(zx::time::infinite(), &packet);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- if (packet.key == kExceptionKey) {
- // Process encountered an exception. Kill it directly rather than
- // letting other handlers process the event. We will get a kProcessKey
- // event when the process actually terminates.
- status_zx = child_process_.kill();
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
- } else if (packet.key == kProcessKey) {
- // Process terminated.
- GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
- GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_PROCESS_TERMINATED);
- process_terminated = true;
- } else if (packet.key == kSocketKey) {
- GTEST_DEATH_TEST_CHECK_(ZX_PKT_IS_SIGNAL_ONE(packet.type));
- if (packet.signal.observed & ZX_SOCKET_READABLE) {
- // Read data from the socket.
- constexpr size_t kBufferSize = 1024;
- do {
- size_t old_length = captured_stderr_.length();
- size_t bytes_read = 0;
- captured_stderr_.resize(old_length + kBufferSize);
- status_zx = stderr_socket_.read(
- 0, &captured_stderr_.front() + old_length, kBufferSize,
- &bytes_read);
- captured_stderr_.resize(old_length + bytes_read);
- } while (status_zx == ZX_OK);
- if (status_zx == ZX_ERR_PEER_CLOSED) {
- socket_closed = true;
- } else {
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_ERR_SHOULD_WAIT);
- status_zx = stderr_socket_.wait_async(
- port, kSocketKey, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED,
- ZX_WAIT_ASYNC_ONCE);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
- }
- } else {
- GTEST_DEATH_TEST_CHECK_(packet.signal.observed & ZX_SOCKET_PEER_CLOSED);
- socket_closed = true;
- }
- }
- } while (!process_terminated && !socket_closed);
-
- ReadAndInterpretStatusByte();
-
- zx_info_process_t buffer;
- status_zx = child_process_.get_info(
- ZX_INFO_PROCESS, &buffer, sizeof(buffer), nullptr, nullptr);
- GTEST_DEATH_TEST_CHECK_(status_zx == ZX_OK);
-
- GTEST_DEATH_TEST_CHECK_(buffer.exited);
- set_status(buffer.return_code);
- return status();
-}
-
-// The AssumeRole process for a Fuchsia death test. It creates a child
-// process with the same executable as the current process to run the
-// death test. The child process is given the --gtest_filter and
-// --gtest_internal_run_death_test flags such that it knows to run the
-// current death test only.
-DeathTest::TestRole FuchsiaDeathTest::AssumeRole() {
- const UnitTestImpl* const impl = GetUnitTestImpl();
- const InternalRunDeathTestFlag* const flag =
- impl->internal_run_death_test_flag();
- const TestInfo* const info = impl->current_test_info();
- const int death_test_index = info->result()->death_test_count();
-
- if (flag != nullptr) {
- // ParseInternalRunDeathTestFlag() has performed all the necessary
- // processing.
- set_write_fd(kFuchsiaReadPipeFd);
- return EXECUTE_TEST;
- }
-
- // Flush the log buffers since the log streams are shared with the child.
- FlushInfoLog();
-
- // Build the child process command line.
- const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
- kFilterFlag + "=" + info->test_suite_name() +
- "." + info->name();
- const std::string internal_flag =
- std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
- + file_ + "|"
- + StreamableToString(line_) + "|"
- + StreamableToString(death_test_index);
- Arguments args;
- args.AddArguments(GetInjectableArgvs());
- args.AddArgument(filter_flag.c_str());
- args.AddArgument(internal_flag.c_str());
-
- // Build the pipe for communication with the child.
- zx_status_t status;
- zx_handle_t child_pipe_handle;
- int child_pipe_fd;
- status = fdio_pipe_half(&child_pipe_fd, &child_pipe_handle);
- GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
- set_read_fd(child_pipe_fd);
-
- // Set the pipe handle for the child.
- fdio_spawn_action_t spawn_actions[2] = {};
- fdio_spawn_action_t* add_handle_action = &spawn_actions[0];
- add_handle_action->action = FDIO_SPAWN_ACTION_ADD_HANDLE;
- add_handle_action->h.id = PA_HND(PA_FD, kFuchsiaReadPipeFd);
- add_handle_action->h.handle = child_pipe_handle;
-
- // Create a socket pair will be used to receive the child process' stderr.
- zx::socket stderr_producer_socket;
- status =
- zx::socket::create(0, &stderr_producer_socket, &stderr_socket_);
- GTEST_DEATH_TEST_CHECK_(status >= 0);
- int stderr_producer_fd = -1;
- status =
- fdio_fd_create(stderr_producer_socket.release(), &stderr_producer_fd);
- GTEST_DEATH_TEST_CHECK_(status >= 0);
-
- // Make the stderr socket nonblocking.
- GTEST_DEATH_TEST_CHECK_(fcntl(stderr_producer_fd, F_SETFL, 0) == 0);
-
- fdio_spawn_action_t* add_stderr_action = &spawn_actions[1];
- add_stderr_action->action = FDIO_SPAWN_ACTION_CLONE_FD;
- add_stderr_action->fd.local_fd = stderr_producer_fd;
- add_stderr_action->fd.target_fd = STDERR_FILENO;
-
- // Create a child job.
- zx_handle_t child_job = ZX_HANDLE_INVALID;
- status = zx_job_create(zx_job_default(), 0, & child_job);
- GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
- zx_policy_basic_t policy;
- policy.condition = ZX_POL_NEW_ANY;
- policy.policy = ZX_POL_ACTION_ALLOW;
- status = zx_job_set_policy(
- child_job, ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy, 1);
- GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
- // Create an exception channel attached to the |child_job|, to allow
- // us to suppress the system default exception handler from firing.
- status =
- zx_task_create_exception_channel(
- child_job, 0, exception_channel_.reset_and_get_address());
- GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
- // Spawn the child process.
- status = fdio_spawn_etc(
- child_job, FDIO_SPAWN_CLONE_ALL, args.Argv()[0], args.Argv(), nullptr,
- 2, spawn_actions, child_process_.reset_and_get_address(), nullptr);
- GTEST_DEATH_TEST_CHECK_(status == ZX_OK);
-
- set_spawned(true);
- return OVERSEE_TEST;
-}
-
-std::string FuchsiaDeathTest::GetErrorLogs() {
- return captured_stderr_;
-}
-
-#else // We are neither on Windows, nor on Fuchsia.
-
-// ForkingDeathTest provides implementations for most of the abstract
-// methods of the DeathTest interface. Only the AssumeRole method is
-// left undefined.
-class ForkingDeathTest : public DeathTestImpl {
- public:
- ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
-
- // All of these virtual functions are inherited from DeathTest.
- int Wait() override;
-
- protected:
- void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
-
- private:
- // PID of child process during death test; 0 in the child process itself.
- pid_t child_pid_;
-};
-
-// Constructs a ForkingDeathTest.
-ForkingDeathTest::ForkingDeathTest(const char* a_statement,
- Matcher<const std::string&> matcher)
- : DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
-
-// Waits for the child in a death test to exit, returning its exit
-// status, or 0 if no child process exists. As a side effect, sets the
-// outcome data member.
-int ForkingDeathTest::Wait() {
- if (!spawned())
- return 0;
-
- ReadAndInterpretStatusByte();
-
- int status_value;
- GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
- set_status(status_value);
- return status_value;
-}
-
-// A concrete death test class that forks, then immediately runs the test
-// in the child process.
-class NoExecDeathTest : public ForkingDeathTest {
- public:
- NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
- : ForkingDeathTest(a_statement, std::move(matcher)) {}
- TestRole AssumeRole() override;
-};
-
-// The AssumeRole process for a fork-and-run death test. It implements a
-// straightforward fork, with a simple pipe to transmit the status byte.
-DeathTest::TestRole NoExecDeathTest::AssumeRole() {
- const size_t thread_count = GetThreadCount();
- if (thread_count != 1) {
- GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
- }
-
- int pipe_fd[2];
- GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
-
- DeathTest::set_last_death_test_message("");
- CaptureStderr();
- // When we fork the process below, the log file buffers are copied, but the
- // file descriptors are shared. We flush all log files here so that closing
- // the file descriptors in the child process doesn't throw off the
- // synchronization between descriptors and buffers in the parent process.
- // This is as close to the fork as possible to avoid a race condition in case
- // there are multiple threads running before the death test, and another
- // thread writes to the log file.
- FlushInfoLog();
-
- const pid_t child_pid = fork();
- GTEST_DEATH_TEST_CHECK_(child_pid != -1);
- set_child_pid(child_pid);
- if (child_pid == 0) {
- GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
- set_write_fd(pipe_fd[1]);
- // Redirects all logging to stderr in the child process to prevent
- // concurrent writes to the log files. We capture stderr in the parent
- // process and append the child process' output to a log.
- LogToStderr();
- // Event forwarding to the listeners of event listener API mush be shut
- // down in death test subprocesses.
- GetUnitTestImpl()->listeners()->SuppressEventForwarding();
- g_in_fast_death_test_child = true;
- return EXECUTE_TEST;
- } else {
- GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
- set_read_fd(pipe_fd[0]);
- set_spawned(true);
- return OVERSEE_TEST;
- }
-}
-
-// A concrete death test class that forks and re-executes the main
-// program from the beginning, with command-line flags set that cause
-// only this specific death test to be run.
-class ExecDeathTest : public ForkingDeathTest {
- public:
- ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
- const char* file, int line)
- : ForkingDeathTest(a_statement, std::move(matcher)),
- file_(file),
- line_(line) {}
- TestRole AssumeRole() override;
-
- private:
- static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
- ::std::vector<std::string> args = GetInjectableArgvs();
-# if defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
- ::std::vector<std::string> extra_args =
- GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_();
- args.insert(args.end(), extra_args.begin(), extra_args.end());
-# endif // defined(GTEST_EXTRA_DEATH_TEST_COMMAND_LINE_ARGS_)
- return args;
- }
- // The name of the file in which the death test is located.
- const char* const file_;
- // The line number on which the death test is located.
- const int line_;
-};
-
-// Utility class for accumulating command-line arguments.
-class Arguments {
- public:
- Arguments() { args_.push_back(nullptr); }
-
- ~Arguments() {
- for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
- ++i) {
- free(*i);
- }
- }
- void AddArgument(const char* argument) {
- args_.insert(args_.end() - 1, posix::StrDup(argument));
- }
-
- template <typename Str>
- void AddArguments(const ::std::vector<Str>& arguments) {
- for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
- i != arguments.end();
- ++i) {
- args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
- }
- }
- char* const* Argv() {
- return &args_[0];
- }
-
- private:
- std::vector<char*> args_;
-};
-
-// A struct that encompasses the arguments to the child process of a
-// threadsafe-style death test process.
-struct ExecDeathTestArgs {
- char* const* argv; // Command-line arguments for the child's call to exec
- int close_fd; // File descriptor to close; the read end of a pipe
-};
-
-# if GTEST_OS_MAC
-inline char** GetEnviron() {
- // When Google Test is built as a framework on MacOS X, the environ variable
- // is unavailable. Apple's documentation (man environ) recommends using
- // _NSGetEnviron() instead.
- return *_NSGetEnviron();
-}
-# else
-// Some POSIX platforms expect you to declare environ. extern "C" makes
-// it reside in the global namespace.
-extern "C" char** environ;
-inline char** GetEnviron() { return environ; }
-# endif // GTEST_OS_MAC
-
-# if !GTEST_OS_QNX
-// The main function for a threadsafe-style death test child process.
-// This function is called in a clone()-ed process and thus must avoid
-// any potentially unsafe operations like malloc or libc functions.
-static int ExecDeathTestChildMain(void* child_arg) {
- ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
- GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
-
- // We need to execute the test program in the same environment where
- // it was originally invoked. Therefore we change to the original
- // working directory first.
- const char* const original_dir =
- UnitTest::GetInstance()->original_working_dir();
- // We can safely call chdir() as it's a direct system call.
- if (chdir(original_dir) != 0) {
- DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
- GetLastErrnoDescription());
- return EXIT_FAILURE;
- }
-
- // We can safely call execve() as it's a direct system call. We
- // cannot use execvp() as it's a libc function and thus potentially
- // unsafe. Since execve() doesn't search the PATH, the user must
- // invoke the test program via a valid path that contains at least
- // one path separator.
- execve(args->argv[0], args->argv, GetEnviron());
- DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
- original_dir + " failed: " +
- GetLastErrnoDescription());
- return EXIT_FAILURE;
-}
-# endif // !GTEST_OS_QNX
-
-# if GTEST_HAS_CLONE
-// Two utility routines that together determine the direction the stack
-// grows.
-// This could be accomplished more elegantly by a single recursive
-// function, but we want to guard against the unlikely possibility of
-// a smart compiler optimizing the recursion away.
-//
-// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
-// StackLowerThanAddress into StackGrowsDown, which then doesn't give
-// correct answer.
-static void StackLowerThanAddress(const void* ptr,
- bool* result) GTEST_NO_INLINE_;
-// HWAddressSanitizer add a random tag to the MSB of the local variable address,
-// making comparison result unpredictable.
-GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-static void StackLowerThanAddress(const void* ptr, bool* result) {
- int dummy;
- *result = (&dummy < ptr);
-}
-
-// Make sure AddressSanitizer does not tamper with the stack here.
-GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-static bool StackGrowsDown() {
- int dummy;
- bool result;
- StackLowerThanAddress(&dummy, &result);
- return result;
-}
-# endif // GTEST_HAS_CLONE
-
-// Spawns a child process with the same executable as the current process in
-// a thread-safe manner and instructs it to run the death test. The
-// implementation uses fork(2) + exec. On systems where clone(2) is
-// available, it is used instead, being slightly more thread-safe. On QNX,
-// fork supports only single-threaded environments, so this function uses
-// spawn(2) there instead. The function dies with an error message if
-// anything goes wrong.
-static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
- ExecDeathTestArgs args = { argv, close_fd };
- pid_t child_pid = -1;
-
-# if GTEST_OS_QNX
- // Obtains the current directory and sets it to be closed in the child
- // process.
- const int cwd_fd = open(".", O_RDONLY);
- GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
- GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
- // We need to execute the test program in the same environment where
- // it was originally invoked. Therefore we change to the original
- // working directory first.
- const char* const original_dir =
- UnitTest::GetInstance()->original_working_dir();
- // We can safely call chdir() as it's a direct system call.
- if (chdir(original_dir) != 0) {
- DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
- GetLastErrnoDescription());
- return EXIT_FAILURE;
- }
-
- int fd_flags;
- // Set close_fd to be closed after spawn.
- GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
- GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
- fd_flags | FD_CLOEXEC));
- struct inheritance inherit = {0};
- // spawn is a system call.
- child_pid =
- spawn(args.argv[0], 0, nullptr, &inherit, args.argv, GetEnviron());
- // Restores the current working directory.
- GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
- GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
-
-# else // GTEST_OS_QNX
-# if GTEST_OS_LINUX
- // When a SIGPROF signal is received while fork() or clone() are executing,
- // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
- // it after the call to fork()/clone() is complete.
- struct sigaction saved_sigprof_action;
- struct sigaction ignore_sigprof_action;
- memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
- sigemptyset(&ignore_sigprof_action.sa_mask);
- ignore_sigprof_action.sa_handler = SIG_IGN;
- GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
- SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
-# endif // GTEST_OS_LINUX
-
-# if GTEST_HAS_CLONE
- const bool use_fork = GTEST_FLAG(death_test_use_fork);
-
- if (!use_fork) {
- static const bool stack_grows_down = StackGrowsDown();
- const auto stack_size = static_cast<size_t>(getpagesize());
- // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
- void* const stack = mmap(nullptr, stack_size, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
-
- // Maximum stack alignment in bytes: For a downward-growing stack, this
- // amount is subtracted from size of the stack space to get an address
- // that is within the stack space and is aligned on all systems we care
- // about. As far as I know there is no ABI with stack alignment greater
- // than 64. We assume stack and stack_size already have alignment of
- // kMaxStackAlignment.
- const size_t kMaxStackAlignment = 64;
- void* const stack_top =
- static_cast<char*>(stack) +
- (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
- GTEST_DEATH_TEST_CHECK_(
- static_cast<size_t>(stack_size) > kMaxStackAlignment &&
- reinterpret_cast<uintptr_t>(stack_top) % kMaxStackAlignment == 0);
-
- child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
-
- GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
- }
-# else
- const bool use_fork = true;
-# endif // GTEST_HAS_CLONE
-
- if (use_fork && (child_pid = fork()) == 0) {
- ExecDeathTestChildMain(&args);
- _exit(0);
- }
-# endif // GTEST_OS_QNX
-# if GTEST_OS_LINUX
- GTEST_DEATH_TEST_CHECK_SYSCALL_(
- sigaction(SIGPROF, &saved_sigprof_action, nullptr));
-# endif // GTEST_OS_LINUX
-
- GTEST_DEATH_TEST_CHECK_(child_pid != -1);
- return child_pid;
-}
-
-// The AssumeRole process for a fork-and-exec death test. It re-executes the
-// main program from the beginning, setting the --gtest_filter
-// and --gtest_internal_run_death_test flags to cause only the current
-// death test to be re-run.
-DeathTest::TestRole ExecDeathTest::AssumeRole() {
- const UnitTestImpl* const impl = GetUnitTestImpl();
- const InternalRunDeathTestFlag* const flag =
- impl->internal_run_death_test_flag();
- const TestInfo* const info = impl->current_test_info();
- const int death_test_index = info->result()->death_test_count();
-
- if (flag != nullptr) {
- set_write_fd(flag->write_fd());
- return EXECUTE_TEST;
- }
-
- int pipe_fd[2];
- GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
- // Clear the close-on-exec flag on the write end of the pipe, lest
- // it be closed when the child process does an exec:
- GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
-
- const std::string filter_flag = std::string("--") + GTEST_FLAG_PREFIX_ +
- kFilterFlag + "=" + info->test_suite_name() +
- "." + info->name();
- const std::string internal_flag =
- std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
- + file_ + "|" + StreamableToString(line_) + "|"
- + StreamableToString(death_test_index) + "|"
- + StreamableToString(pipe_fd[1]);
- Arguments args;
- args.AddArguments(GetArgvsForDeathTestChildProcess());
- args.AddArgument(filter_flag.c_str());
- args.AddArgument(internal_flag.c_str());
-
- DeathTest::set_last_death_test_message("");
-
- CaptureStderr();
- // See the comment in NoExecDeathTest::AssumeRole for why the next line
- // is necessary.
- FlushInfoLog();
-
- const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
- GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
- set_child_pid(child_pid);
- set_read_fd(pipe_fd[0]);
- set_spawned(true);
- return OVERSEE_TEST;
-}
-
-# endif // !GTEST_OS_WINDOWS
-
-// Creates a concrete DeathTest-derived class that depends on the
-// --gtest_death_test_style flag, and sets the pointer pointed to
-// by the "test" argument to its address. If the test should be
-// skipped, sets that pointer to NULL. Returns true, unless the
-// flag is set to an invalid value.
-bool DefaultDeathTestFactory::Create(const char* statement,
- Matcher<const std::string&> matcher,
- const char* file, int line,
- DeathTest** test) {
- UnitTestImpl* const impl = GetUnitTestImpl();
- const InternalRunDeathTestFlag* const flag =
- impl->internal_run_death_test_flag();
- const int death_test_index = impl->current_test_info()
- ->increment_death_test_count();
-
- if (flag != nullptr) {
- if (death_test_index > flag->index()) {
- DeathTest::set_last_death_test_message(
- "Death test count (" + StreamableToString(death_test_index)
- + ") somehow exceeded expected maximum ("
- + StreamableToString(flag->index()) + ")");
- return false;
- }
-
- if (!(flag->file() == file && flag->line() == line &&
- flag->index() == death_test_index)) {
- *test = nullptr;
- return true;
- }
- }
-
-# if GTEST_OS_WINDOWS
-
- if (GTEST_FLAG(death_test_style) == "threadsafe" ||
- GTEST_FLAG(death_test_style) == "fast") {
- *test = new WindowsDeathTest(statement, std::move(matcher), file, line);
- }
-
-# elif GTEST_OS_FUCHSIA
-
- if (GTEST_FLAG(death_test_style) == "threadsafe" ||
- GTEST_FLAG(death_test_style) == "fast") {
- *test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
- }
-
-# else
-
- if (GTEST_FLAG(death_test_style) == "threadsafe") {
- *test = new ExecDeathTest(statement, std::move(matcher), file, line);
- } else if (GTEST_FLAG(death_test_style) == "fast") {
- *test = new NoExecDeathTest(statement, std::move(matcher));
- }
-
-# endif // GTEST_OS_WINDOWS
-
- else { // NOLINT - this is more readable than unbalanced brackets inside #if.
- DeathTest::set_last_death_test_message(
- "Unknown death test style \"" + GTEST_FLAG(death_test_style)
- + "\" encountered");
- return false;
- }
-
- return true;
-}
-
-# if GTEST_OS_WINDOWS
-// Recreates the pipe and event handles from the provided parameters,
-// signals the event, and returns a file descriptor wrapped around the pipe
-// handle. This function is called in the child process only.
-static int GetStatusFileDescriptor(unsigned int parent_process_id,
- size_t write_handle_as_size_t,
- size_t event_handle_as_size_t) {
- AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
- FALSE, // Non-inheritable.
- parent_process_id));
- if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
- DeathTestAbort("Unable to open parent process " +
- StreamableToString(parent_process_id));
- }
-
- GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
-
- const HANDLE write_handle =
- reinterpret_cast<HANDLE>(write_handle_as_size_t);
- HANDLE dup_write_handle;
-
- // The newly initialized handle is accessible only in the parent
- // process. To obtain one accessible within the child, we need to use
- // DuplicateHandle.
- if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
- ::GetCurrentProcess(), &dup_write_handle,
- 0x0, // Requested privileges ignored since
- // DUPLICATE_SAME_ACCESS is used.
- FALSE, // Request non-inheritable handler.
- DUPLICATE_SAME_ACCESS)) {
- DeathTestAbort("Unable to duplicate the pipe handle " +
- StreamableToString(write_handle_as_size_t) +
- " from the parent process " +
- StreamableToString(parent_process_id));
- }
-
- const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
- HANDLE dup_event_handle;
-
- if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
- ::GetCurrentProcess(), &dup_event_handle,
- 0x0,
- FALSE,
- DUPLICATE_SAME_ACCESS)) {
- DeathTestAbort("Unable to duplicate the event handle " +
- StreamableToString(event_handle_as_size_t) +
- " from the parent process " +
- StreamableToString(parent_process_id));
- }
-
- const int write_fd =
- ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
- if (write_fd == -1) {
- DeathTestAbort("Unable to convert pipe handle " +
- StreamableToString(write_handle_as_size_t) +
- " to a file descriptor");
- }
-
- // Signals the parent that the write end of the pipe has been acquired
- // so the parent can release its own write end.
- ::SetEvent(dup_event_handle);
-
- return write_fd;
-}
-# endif // GTEST_OS_WINDOWS
-
-// Returns a newly created InternalRunDeathTestFlag object with fields
-// initialized from the GTEST_FLAG(internal_run_death_test) flag if
-// the flag is specified; otherwise returns NULL.
-InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
- if (GTEST_FLAG(internal_run_death_test) == "") return nullptr;
-
- // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
- // can use it here.
- int line = -1;
- int index = -1;
- ::std::vector< ::std::string> fields;
- SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
- int write_fd = -1;
-
-# if GTEST_OS_WINDOWS
-
- unsigned int parent_process_id = 0;
- size_t write_handle_as_size_t = 0;
- size_t event_handle_as_size_t = 0;
-
- if (fields.size() != 6
- || !ParseNaturalNumber(fields[1], &line)
- || !ParseNaturalNumber(fields[2], &index)
- || !ParseNaturalNumber(fields[3], &parent_process_id)
- || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
- || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
- DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
- GTEST_FLAG(internal_run_death_test));
- }
- write_fd = GetStatusFileDescriptor(parent_process_id,
- write_handle_as_size_t,
- event_handle_as_size_t);
-
-# elif GTEST_OS_FUCHSIA
-
- if (fields.size() != 3
- || !ParseNaturalNumber(fields[1], &line)
- || !ParseNaturalNumber(fields[2], &index)) {
- DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
- + GTEST_FLAG(internal_run_death_test));
- }
-
-# else
-
- if (fields.size() != 4
- || !ParseNaturalNumber(fields[1], &line)
- || !ParseNaturalNumber(fields[2], &index)
- || !ParseNaturalNumber(fields[3], &write_fd)) {
- DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
- + GTEST_FLAG(internal_run_death_test));
- }
-
-# endif // GTEST_OS_WINDOWS
-
- return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
-}
-
-} // namespace internal
-
-#endif // GTEST_HAS_DEATH_TEST
-
-} // namespace testing
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "gtest/internal/gtest-filepath.h"
-
-#include <stdlib.h>
-#include "gtest/internal/gtest-port.h"
-#include "gtest/gtest-message.h"
-
-#if GTEST_OS_WINDOWS_MOBILE
-# include <windows.h>
-#elif GTEST_OS_WINDOWS
-# include <direct.h>
-# include <io.h>
-#else
-# include <limits.h>
-# include <climits> // Some Linux distributions define PATH_MAX here.
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-#include "gtest/internal/gtest-string.h"
-
-#if GTEST_OS_WINDOWS
-# define GTEST_PATH_MAX_ _MAX_PATH
-#elif defined(PATH_MAX)
-# define GTEST_PATH_MAX_ PATH_MAX
-#elif defined(_XOPEN_PATH_MAX)
-# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
-#else
-# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
-#endif // GTEST_OS_WINDOWS
-
-namespace testing {
-namespace internal {
-
-#if GTEST_OS_WINDOWS
-// On Windows, '\\' is the standard path separator, but many tools and the
-// Windows API also accept '/' as an alternate path separator. Unless otherwise
-// noted, a file path can contain either kind of path separators, or a mixture
-// of them.
-const char kPathSeparator = '\\';
-const char kAlternatePathSeparator = '/';
-const char kAlternatePathSeparatorString[] = "/";
-# if GTEST_OS_WINDOWS_MOBILE
-// Windows CE doesn't have a current directory. You should not use
-// the current directory in tests on Windows CE, but this at least
-// provides a reasonable fallback.
-const char kCurrentDirectoryString[] = "\\";
-// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
-const DWORD kInvalidFileAttributes = 0xffffffff;
-# else
-const char kCurrentDirectoryString[] = ".\\";
-# endif // GTEST_OS_WINDOWS_MOBILE
-#else
-const char kPathSeparator = '/';
-const char kCurrentDirectoryString[] = "./";
-#endif // GTEST_OS_WINDOWS
-
-// Returns whether the given character is a valid path separator.
-static bool IsPathSeparator(char c) {
-#if GTEST_HAS_ALT_PATH_SEP_
- return (c == kPathSeparator) || (c == kAlternatePathSeparator);
-#else
- return c == kPathSeparator;
-#endif
-}
-
-// Returns the current working directory, or "" if unsuccessful.
-FilePath FilePath::GetCurrentDir() {
-#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \
- GTEST_OS_WINDOWS_RT || ARDUINO || defined(ESP_PLATFORM)
- // These platforms do not have a current directory, so we just return
- // something reasonable.
- return FilePath(kCurrentDirectoryString);
-#elif GTEST_OS_WINDOWS
- char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
- return FilePath(_getcwd(cwd, sizeof(cwd)) == nullptr ? "" : cwd);
-#else
- char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
- char* result = getcwd(cwd, sizeof(cwd));
-# if GTEST_OS_NACL
- // getcwd will likely fail in NaCl due to the sandbox, so return something
- // reasonable. The user may have provided a shim implementation for getcwd,
- // however, so fallback only when failure is detected.
- return FilePath(result == nullptr ? kCurrentDirectoryString : cwd);
-# endif // GTEST_OS_NACL
- return FilePath(result == nullptr ? "" : cwd);
-#endif // GTEST_OS_WINDOWS_MOBILE
-}
-
-// Returns a copy of the FilePath with the case-insensitive extension removed.
-// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
-// FilePath("dir/file"). If a case-insensitive extension is not
-// found, returns a copy of the original FilePath.
-FilePath FilePath::RemoveExtension(const char* extension) const {
- const std::string dot_extension = std::string(".") + extension;
- if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
- return FilePath(pathname_.substr(
- 0, pathname_.length() - dot_extension.length()));
- }
- return *this;
-}
-
-// Returns a pointer to the last occurrence of a valid path separator in
-// the FilePath. On Windows, for example, both '/' and '\' are valid path
-// separators. Returns NULL if no path separator was found.
-const char* FilePath::FindLastPathSeparator() const {
- const char* const last_sep = strrchr(c_str(), kPathSeparator);
-#if GTEST_HAS_ALT_PATH_SEP_
- const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
- // Comparing two pointers of which only one is NULL is undefined.
- if (last_alt_sep != nullptr &&
- (last_sep == nullptr || last_alt_sep > last_sep)) {
- return last_alt_sep;
- }
-#endif
- return last_sep;
-}
-
-// Returns a copy of the FilePath with the directory part removed.
-// Example: FilePath("path/to/file").RemoveDirectoryName() returns
-// FilePath("file"). If there is no directory part ("just_a_file"), it returns
-// the FilePath unmodified. If there is no file part ("just_a_dir/") it
-// returns an empty FilePath ("").
-// On Windows platform, '\' is the path separator, otherwise it is '/'.
-FilePath FilePath::RemoveDirectoryName() const {
- const char* const last_sep = FindLastPathSeparator();
- return last_sep ? FilePath(last_sep + 1) : *this;
-}
-
-// RemoveFileName returns the directory path with the filename removed.
-// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
-// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
-// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
-// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
-// On Windows platform, '\' is the path separator, otherwise it is '/'.
-FilePath FilePath::RemoveFileName() const {
- const char* const last_sep = FindLastPathSeparator();
- std::string dir;
- if (last_sep) {
- dir = std::string(c_str(), static_cast<size_t>(last_sep + 1 - c_str()));
- } else {
- dir = kCurrentDirectoryString;
- }
- return FilePath(dir);
-}
-
-// Helper functions for naming files in a directory for xml output.
-
-// Given directory = "dir", base_name = "test", number = 0,
-// extension = "xml", returns "dir/test.xml". If number is greater
-// than zero (e.g., 12), returns "dir/test_12.xml".
-// On Windows platform, uses \ as the separator rather than /.
-FilePath FilePath::MakeFileName(const FilePath& directory,
- const FilePath& base_name,
- int number,
- const char* extension) {
- std::string file;
- if (number == 0) {
- file = base_name.string() + "." + extension;
- } else {
- file = base_name.string() + "_" + StreamableToString(number)
- + "." + extension;
- }
- return ConcatPaths(directory, FilePath(file));
-}
-
-// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
-// On Windows, uses \ as the separator rather than /.
-FilePath FilePath::ConcatPaths(const FilePath& directory,
- const FilePath& relative_path) {
- if (directory.IsEmpty())
- return relative_path;
- const FilePath dir(directory.RemoveTrailingPathSeparator());
- return FilePath(dir.string() + kPathSeparator + relative_path.string());
-}
-
-// Returns true if pathname describes something findable in the file-system,
-// either a file, directory, or whatever.
-bool FilePath::FileOrDirectoryExists() const {
-#if GTEST_OS_WINDOWS_MOBILE
- LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
- const DWORD attributes = GetFileAttributes(unicode);
- delete [] unicode;
- return attributes != kInvalidFileAttributes;
-#else
- posix::StatStruct file_stat;
- return posix::Stat(pathname_.c_str(), &file_stat) == 0;
-#endif // GTEST_OS_WINDOWS_MOBILE
-}
-
-// Returns true if pathname describes a directory in the file-system
-// that exists.
-bool FilePath::DirectoryExists() const {
- bool result = false;
-#if GTEST_OS_WINDOWS
- // Don't strip off trailing separator if path is a root directory on
- // Windows (like "C:\\").
- const FilePath& path(IsRootDirectory() ? *this :
- RemoveTrailingPathSeparator());
-#else
- const FilePath& path(*this);
-#endif
-
-#if GTEST_OS_WINDOWS_MOBILE
- LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
- const DWORD attributes = GetFileAttributes(unicode);
- delete [] unicode;
- if ((attributes != kInvalidFileAttributes) &&
- (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
- result = true;
- }
-#else
- posix::StatStruct file_stat;
- result = posix::Stat(path.c_str(), &file_stat) == 0 &&
- posix::IsDir(file_stat);
-#endif // GTEST_OS_WINDOWS_MOBILE
-
- return result;
-}
-
-// Returns true if pathname describes a root directory. (Windows has one
-// root directory per disk drive.)
-bool FilePath::IsRootDirectory() const {
-#if GTEST_OS_WINDOWS
- return pathname_.length() == 3 && IsAbsolutePath();
-#else
- return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
-#endif
-}
-
-// Returns true if pathname describes an absolute path.
-bool FilePath::IsAbsolutePath() const {
- const char* const name = pathname_.c_str();
-#if GTEST_OS_WINDOWS
- return pathname_.length() >= 3 &&
- ((name[0] >= 'a' && name[0] <= 'z') ||
- (name[0] >= 'A' && name[0] <= 'Z')) &&
- name[1] == ':' &&
- IsPathSeparator(name[2]);
-#else
- return IsPathSeparator(name[0]);
-#endif
-}
-
-// Returns a pathname for a file that does not currently exist. The pathname
-// will be directory/base_name.extension or
-// directory/base_name_<number>.extension if directory/base_name.extension
-// already exists. The number will be incremented until a pathname is found
-// that does not already exist.
-// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
-// There could be a race condition if two or more processes are calling this
-// function at the same time -- they could both pick the same filename.
-FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
- const FilePath& base_name,
- const char* extension) {
- FilePath full_pathname;
- int number = 0;
- do {
- full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
- } while (full_pathname.FileOrDirectoryExists());
- return full_pathname;
-}
-
-// Returns true if FilePath ends with a path separator, which indicates that
-// it is intended to represent a directory. Returns false otherwise.
-// This does NOT check that a directory (or file) actually exists.
-bool FilePath::IsDirectory() const {
- return !pathname_.empty() &&
- IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
-}
-
-// Create directories so that path exists. Returns true if successful or if
-// the directories already exist; returns false if unable to create directories
-// for any reason.
-bool FilePath::CreateDirectoriesRecursively() const {
- if (!this->IsDirectory()) {
- return false;
- }
-
- if (pathname_.length() == 0 || this->DirectoryExists()) {
- return true;
- }
-
- const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
- return parent.CreateDirectoriesRecursively() && this->CreateFolder();
-}
-
-// Create the directory so that path exists. Returns true if successful or
-// if the directory already exists; returns false if unable to create the
-// directory for any reason, including if the parent directory does not
-// exist. Not named "CreateDirectory" because that's a macro on Windows.
-bool FilePath::CreateFolder() const {
-#if GTEST_OS_WINDOWS_MOBILE
- FilePath removed_sep(this->RemoveTrailingPathSeparator());
- LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
- int result = CreateDirectory(unicode, nullptr) ? 0 : -1;
- delete [] unicode;
-#elif GTEST_OS_WINDOWS
- int result = _mkdir(pathname_.c_str());
-#else
- int result = mkdir(pathname_.c_str(), 0777);
-#endif // GTEST_OS_WINDOWS_MOBILE
-
- if (result == -1) {
- return this->DirectoryExists(); // An error is OK if the directory exists.
- }
- return true; // No error.
-}
-
-// If input name has a trailing separator character, remove it and return the
-// name, otherwise return the name string unmodified.
-// On Windows platform, uses \ as the separator, other platforms use /.
-FilePath FilePath::RemoveTrailingPathSeparator() const {
- return IsDirectory()
- ? FilePath(pathname_.substr(0, pathname_.length() - 1))
- : *this;
-}
-
-// Removes any redundant separators that might be in the pathname.
-// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
-// redundancies that might be in a pathname involving "." or "..".
-void FilePath::Normalize() {
- if (pathname_.c_str() == nullptr) {
- pathname_ = "";
- return;
- }
- const char* src = pathname_.c_str();
- char* const dest = new char[pathname_.length() + 1];
- char* dest_ptr = dest;
- memset(dest_ptr, 0, pathname_.length() + 1);
-
- while (*src != '\0') {
- *dest_ptr = *src;
- if (!IsPathSeparator(*src)) {
- src++;
- } else {
-#if GTEST_HAS_ALT_PATH_SEP_
- if (*dest_ptr == kAlternatePathSeparator) {
- *dest_ptr = kPathSeparator;
- }
-#endif
- while (IsPathSeparator(*src))
- src++;
- }
- dest_ptr++;
- }
- *dest_ptr = '\0';
- pathname_ = dest;
- delete[] dest;
-}
-
-} // namespace internal
-} // namespace testing
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Utility functions and classes used by the Google C++ testing framework.//
-// This file contains purely Google Test's internal implementation. Please
-// DO NOT #INCLUDE IT IN A USER PROGRAM.
-
-#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
-#define GTEST_SRC_GTEST_INTERNAL_INL_H_
-
-#ifndef _WIN32_WCE
-# include <errno.h>
-#endif // !_WIN32_WCE
-#include <stddef.h>
-#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
-#include <string.h> // For memmove.
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "gtest/internal/gtest-port.h"
-
-#if GTEST_CAN_STREAM_RESULTS_
-# include <arpa/inet.h> // NOLINT
-# include <netdb.h> // NOLINT
-#endif
-
-#if GTEST_OS_WINDOWS
-# include <windows.h> // NOLINT
-#endif // GTEST_OS_WINDOWS
-
-#include "gtest/gtest.h"
-#include "gtest/gtest-spi.h"
-
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
-/* class A needs to have dll-interface to be used by clients of class B */)
-
-namespace testing {
-
-// Declares the flags.
-//
-// We don't want the users to modify this flag in the code, but want
-// Google Test's own unit tests to be able to access it. Therefore we
-// declare it here as opposed to in gtest.h.
-GTEST_DECLARE_bool_(death_test_use_fork);
-
-namespace internal {
-
-// The value of GetTestTypeId() as seen from within the Google Test
-// library. This is solely for testing GetTestTypeId().
-GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
-
-// Names of the flags (needed for parsing Google Test flags).
-const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
-const char kBreakOnFailureFlag[] = "break_on_failure";
-const char kCatchExceptionsFlag[] = "catch_exceptions";
-const char kColorFlag[] = "color";
-const char kFilterFlag[] = "filter";
-const char kListTestsFlag[] = "list_tests";
-const char kOutputFlag[] = "output";
-const char kPrintTimeFlag[] = "print_time";
-const char kPrintUTF8Flag[] = "print_utf8";
-const char kRandomSeedFlag[] = "random_seed";
-const char kRepeatFlag[] = "repeat";
-const char kShuffleFlag[] = "shuffle";
-const char kStackTraceDepthFlag[] = "stack_trace_depth";
-const char kStreamResultToFlag[] = "stream_result_to";
-const char kThrowOnFailureFlag[] = "throw_on_failure";
-const char kFlagfileFlag[] = "flagfile";
-
-// A valid random seed must be in [1, kMaxRandomSeed].
-const int kMaxRandomSeed = 99999;
-
-// g_help_flag is true if and only if the --help flag or an equivalent form
-// is specified on the command line.
-GTEST_API_ extern bool g_help_flag;
-
-// Returns the current time in milliseconds.
-GTEST_API_ TimeInMillis GetTimeInMillis();
-
-// Returns true if and only if Google Test should use colors in the output.
-GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
-
-// Formats the given time in milliseconds as seconds.
-GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
-
-// Converts the given time in milliseconds to a date string in the ISO 8601
-// format, without the timezone information. N.B.: due to the use the
-// non-reentrant localtime() function, this function is not thread safe. Do
-// not use it in any code that can be called from multiple threads.
-GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
-
-// Parses a string for an Int32 flag, in the form of "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-GTEST_API_ bool ParseInt32Flag(
- const char* str, const char* flag, Int32* value);
-
-// Returns a random seed in range [1, kMaxRandomSeed] based on the
-// given --gtest_random_seed flag value.
-inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
- const unsigned int raw_seed = (random_seed_flag == 0) ?
- static_cast<unsigned int>(GetTimeInMillis()) :
- static_cast<unsigned int>(random_seed_flag);
-
- // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
- // it's easy to type.
- const int normalized_seed =
- static_cast<int>((raw_seed - 1U) %
- static_cast<unsigned int>(kMaxRandomSeed)) + 1;
- return normalized_seed;
-}
-
-// Returns the first valid random seed after 'seed'. The behavior is
-// undefined if 'seed' is invalid. The seed after kMaxRandomSeed is
-// considered to be 1.
-inline int GetNextRandomSeed(int seed) {
- GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
- << "Invalid random seed " << seed << " - must be in [1, "
- << kMaxRandomSeed << "].";
- const int next_seed = seed + 1;
- return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
-}
-
-// This class saves the values of all Google Test flags in its c'tor, and
-// restores them in its d'tor.
-class GTestFlagSaver {
- public:
- // The c'tor.
- GTestFlagSaver() {
- also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
- break_on_failure_ = GTEST_FLAG(break_on_failure);
- catch_exceptions_ = GTEST_FLAG(catch_exceptions);
- color_ = GTEST_FLAG(color);
- death_test_style_ = GTEST_FLAG(death_test_style);
- death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
- filter_ = GTEST_FLAG(filter);
- internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
- list_tests_ = GTEST_FLAG(list_tests);
- output_ = GTEST_FLAG(output);
- print_time_ = GTEST_FLAG(print_time);
- print_utf8_ = GTEST_FLAG(print_utf8);
- random_seed_ = GTEST_FLAG(random_seed);
- repeat_ = GTEST_FLAG(repeat);
- shuffle_ = GTEST_FLAG(shuffle);
- stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
- stream_result_to_ = GTEST_FLAG(stream_result_to);
- throw_on_failure_ = GTEST_FLAG(throw_on_failure);
- }
-
- // The d'tor is not virtual. DO NOT INHERIT FROM THIS CLASS.
- ~GTestFlagSaver() {
- GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
- GTEST_FLAG(break_on_failure) = break_on_failure_;
- GTEST_FLAG(catch_exceptions) = catch_exceptions_;
- GTEST_FLAG(color) = color_;
- GTEST_FLAG(death_test_style) = death_test_style_;
- GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
- GTEST_FLAG(filter) = filter_;
- GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
- GTEST_FLAG(list_tests) = list_tests_;
- GTEST_FLAG(output) = output_;
- GTEST_FLAG(print_time) = print_time_;
- GTEST_FLAG(print_utf8) = print_utf8_;
- GTEST_FLAG(random_seed) = random_seed_;
- GTEST_FLAG(repeat) = repeat_;
- GTEST_FLAG(shuffle) = shuffle_;
- GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
- GTEST_FLAG(stream_result_to) = stream_result_to_;
- GTEST_FLAG(throw_on_failure) = throw_on_failure_;
- }
-
- private:
- // Fields for saving the original values of flags.
- bool also_run_disabled_tests_;
- bool break_on_failure_;
- bool catch_exceptions_;
- std::string color_;
- std::string death_test_style_;
- bool death_test_use_fork_;
- std::string filter_;
- std::string internal_run_death_test_;
- bool list_tests_;
- std::string output_;
- bool print_time_;
- bool print_utf8_;
- internal::Int32 random_seed_;
- internal::Int32 repeat_;
- bool shuffle_;
- internal::Int32 stack_trace_depth_;
- std::string stream_result_to_;
- bool throw_on_failure_;
-} GTEST_ATTRIBUTE_UNUSED_;
-
-// Converts a Unicode code point to a narrow string in UTF-8 encoding.
-// code_point parameter is of type UInt32 because wchar_t may not be
-// wide enough to contain a code point.
-// If the code_point is not a valid Unicode code point
-// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
-// to "(Invalid Unicode 0xXXXXXXXX)".
-GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
-
-// Converts a wide string to a narrow string in UTF-8 encoding.
-// The wide string is assumed to have the following encoding:
-// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
-// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
-// Parameter str points to a null-terminated wide string.
-// Parameter num_chars may additionally limit the number
-// of wchar_t characters processed. -1 is used when the entire string
-// should be processed.
-// If the string contains code points that are not valid Unicode code points
-// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
-// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
-// and contains invalid UTF-16 surrogate pairs, values in those pairs
-// will be encoded as individual Unicode characters from Basic Normal Plane.
-GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
-
-// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
-// if the variable is present. If a file already exists at this location, this
-// function will write over it. If the variable is present, but the file cannot
-// be created, prints an error and exits.
-void WriteToShardStatusFileIfNeeded();
-
-// Checks whether sharding is enabled by examining the relevant
-// environment variable values. If the variables are present,
-// but inconsistent (e.g., shard_index >= total_shards), prints
-// an error and exits. If in_subprocess_for_death_test, sharding is
-// disabled because it must only be applied to the original test
-// process. Otherwise, we could filter out death tests we intended to execute.
-GTEST_API_ bool ShouldShard(const char* total_shards_str,
- const char* shard_index_str,
- bool in_subprocess_for_death_test);
-
-// Parses the environment variable var as an Int32. If it is unset,
-// returns default_val. If it is not an Int32, prints an error and
-// and aborts.
-GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
-
-// Given the total number of shards, the shard index, and the test id,
-// returns true if and only if the test should be run on this shard. The test id
-// is some arbitrary but unique non-negative integer assigned to each test
-// method. Assumes that 0 <= shard_index < total_shards.
-GTEST_API_ bool ShouldRunTestOnShard(
- int total_shards, int shard_index, int test_id);
-
-// STL container utilities.
-
-// Returns the number of elements in the given container that satisfy
-// the given predicate.
-template <class Container, typename Predicate>
-inline int CountIf(const Container& c, Predicate predicate) {
- // Implemented as an explicit loop since std::count_if() in libCstd on
- // Solaris has a non-standard signature.
- int count = 0;
- for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
- if (predicate(*it))
- ++count;
- }
- return count;
-}
-
-// Applies a function/functor to each element in the container.
-template <class Container, typename Functor>
-void ForEach(const Container& c, Functor functor) {
- std::for_each(c.begin(), c.end(), functor);
-}
-
-// Returns the i-th element of the vector, or default_value if i is not
-// in range [0, v.size()).
-template <typename E>
-inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
- return (i < 0 || i >= static_cast<int>(v.size())) ? default_value
- : v[static_cast<size_t>(i)];
-}
-
-// Performs an in-place shuffle of a range of the vector's elements.
-// 'begin' and 'end' are element indices as an STL-style range;
-// i.e. [begin, end) are shuffled, where 'end' == size() means to
-// shuffle to the end of the vector.
-template <typename E>
-void ShuffleRange(internal::Random* random, int begin, int end,
- std::vector<E>* v) {
- const int size = static_cast<int>(v->size());
- GTEST_CHECK_(0 <= begin && begin <= size)
- << "Invalid shuffle range start " << begin << ": must be in range [0, "
- << size << "].";
- GTEST_CHECK_(begin <= end && end <= size)
- << "Invalid shuffle range finish " << end << ": must be in range ["
- << begin << ", " << size << "].";
-
- // Fisher-Yates shuffle, from
- // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
- for (int range_width = end - begin; range_width >= 2; range_width--) {
- const int last_in_range = begin + range_width - 1;
- const int selected =
- begin +
- static_cast<int>(random->Generate(static_cast<UInt32>(range_width)));
- std::swap((*v)[static_cast<size_t>(selected)],
- (*v)[static_cast<size_t>(last_in_range)]);
- }
-}
-
-// Performs an in-place shuffle of the vector's elements.
-template <typename E>
-inline void Shuffle(internal::Random* random, std::vector<E>* v) {
- ShuffleRange(random, 0, static_cast<int>(v->size()), v);
-}
-
-// A function for deleting an object. Handy for being used as a
-// functor.
-template <typename T>
-static void Delete(T* x) {
- delete x;
-}
-
-// A predicate that checks the key of a TestProperty against a known key.
-//
-// TestPropertyKeyIs is copyable.
-class TestPropertyKeyIs {
- public:
- // Constructor.
- //
- // TestPropertyKeyIs has NO default constructor.
- explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
-
- // Returns true if and only if the test name of test property matches on key_.
- bool operator()(const TestProperty& test_property) const {
- return test_property.key() == key_;
- }
-
- private:
- std::string key_;
-};
-
-// Class UnitTestOptions.
-//
-// This class contains functions for processing options the user
-// specifies when running the tests. It has only static members.
-//
-// In most cases, the user can specify an option using either an
-// environment variable or a command line flag. E.g. you can set the
-// test filter using either GTEST_FILTER or --gtest_filter. If both
-// the variable and the flag are present, the latter overrides the
-// former.
-class GTEST_API_ UnitTestOptions {
- public:
- // Functions for processing the gtest_output flag.
-
- // Returns the output format, or "" for normal printed output.
- static std::string GetOutputFormat();
-
- // Returns the absolute path of the requested output file, or the
- // default (test_detail.xml in the original working directory) if
- // none was explicitly specified.
- static std::string GetAbsolutePathToOutputFile();
-
- // Functions for processing the gtest_filter flag.
-
- // Returns true if and only if the wildcard pattern matches the string.
- // The first ':' or '\0' character in pattern marks the end of it.
- //
- // This recursive algorithm isn't very efficient, but is clear and
- // works well enough for matching test names, which are short.
- static bool PatternMatchesString(const char *pattern, const char *str);
-
- // Returns true if and only if the user-specified filter matches the test
- // suite name and the test name.
- static bool FilterMatchesTest(const std::string& test_suite_name,
- const std::string& test_name);
-
-#if GTEST_OS_WINDOWS
- // Function for supporting the gtest_catch_exception flag.
-
- // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
- // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
- // This function is useful as an __except condition.
- static int GTestShouldProcessSEH(DWORD exception_code);
-#endif // GTEST_OS_WINDOWS
-
- // Returns true if "name" matches the ':' separated list of glob-style
- // filters in "filter".
- static bool MatchesFilter(const std::string& name, const char* filter);
-};
-
-// Returns the current application's name, removing directory path if that
-// is present. Used by UnitTestOptions::GetOutputFile.
-GTEST_API_ FilePath GetCurrentExecutableName();
-
-// The role interface for getting the OS stack trace as a string.
-class OsStackTraceGetterInterface {
- public:
- OsStackTraceGetterInterface() {}
- virtual ~OsStackTraceGetterInterface() {}
-
- // Returns the current OS stack trace as an std::string. Parameters:
- //
- // max_depth - the maximum number of stack frames to be included
- // in the trace.
- // skip_count - the number of top frames to be skipped; doesn't count
- // against max_depth.
- virtual std::string CurrentStackTrace(int max_depth, int skip_count) = 0;
-
- // UponLeavingGTest() should be called immediately before Google Test calls
- // user code. It saves some information about the current stack that
- // CurrentStackTrace() will use to find and hide Google Test stack frames.
- virtual void UponLeavingGTest() = 0;
-
- // This string is inserted in place of stack frames that are part of
- // Google Test's implementation.
- static const char* const kElidedFramesMarker;
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
-};
-
-// A working implementation of the OsStackTraceGetterInterface interface.
-class OsStackTraceGetter : public OsStackTraceGetterInterface {
- public:
- OsStackTraceGetter() {}
-
- std::string CurrentStackTrace(int max_depth, int skip_count) override;
- void UponLeavingGTest() override;
-
- private:
-#if GTEST_HAS_ABSL
- Mutex mutex_; // Protects all internal state.
-
- // We save the stack frame below the frame that calls user code.
- // We do this because the address of the frame immediately below
- // the user code changes between the call to UponLeavingGTest()
- // and any calls to the stack trace code from within the user code.
- void* caller_frame_ = nullptr;
-#endif // GTEST_HAS_ABSL
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
-};
-
-// Information about a Google Test trace point.
-struct TraceInfo {
- const char* file;
- int line;
- std::string message;
-};
-
-// This is the default global test part result reporter used in UnitTestImpl.
-// This class should only be used by UnitTestImpl.
-class DefaultGlobalTestPartResultReporter
- : public TestPartResultReporterInterface {
- public:
- explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
- // Implements the TestPartResultReporterInterface. Reports the test part
- // result in the current test.
- void ReportTestPartResult(const TestPartResult& result) override;
-
- private:
- UnitTestImpl* const unit_test_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
-};
-
-// This is the default per thread test part result reporter used in
-// UnitTestImpl. This class should only be used by UnitTestImpl.
-class DefaultPerThreadTestPartResultReporter
- : public TestPartResultReporterInterface {
- public:
- explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
- // Implements the TestPartResultReporterInterface. The implementation just
- // delegates to the current global test part result reporter of *unit_test_.
- void ReportTestPartResult(const TestPartResult& result) override;
-
- private:
- UnitTestImpl* const unit_test_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
-};
-
-// The private implementation of the UnitTest class. We don't protect
-// the methods under a mutex, as this class is not accessible by a
-// user and the UnitTest class that delegates work to this class does
-// proper locking.
-class GTEST_API_ UnitTestImpl {
- public:
- explicit UnitTestImpl(UnitTest* parent);
- virtual ~UnitTestImpl();
-
- // There are two different ways to register your own TestPartResultReporter.
- // You can register your own repoter to listen either only for test results
- // from the current thread or for results from all threads.
- // By default, each per-thread test result repoter just passes a new
- // TestPartResult to the global test result reporter, which registers the
- // test part result for the currently running test.
-
- // Returns the global test part result reporter.
- TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
-
- // Sets the global test part result reporter.
- void SetGlobalTestPartResultReporter(
- TestPartResultReporterInterface* reporter);
-
- // Returns the test part result reporter for the current thread.
- TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
-
- // Sets the test part result reporter for the current thread.
- void SetTestPartResultReporterForCurrentThread(
- TestPartResultReporterInterface* reporter);
-
- // Gets the number of successful test suites.
- int successful_test_suite_count() const;
-
- // Gets the number of failed test suites.
- int failed_test_suite_count() const;
-
- // Gets the number of all test suites.
- int total_test_suite_count() const;
-
- // Gets the number of all test suites that contain at least one test
- // that should run.
- int test_suite_to_run_count() const;
-
- // Gets the number of successful tests.
- int successful_test_count() const;
-
- // Gets the number of skipped tests.
- int skipped_test_count() const;
-
- // Gets the number of failed tests.
- int failed_test_count() const;
-
- // Gets the number of disabled tests that will be reported in the XML report.
- int reportable_disabled_test_count() const;
-
- // Gets the number of disabled tests.
- int disabled_test_count() const;
-
- // Gets the number of tests to be printed in the XML report.
- int reportable_test_count() const;
-
- // Gets the number of all tests.
- int total_test_count() const;
-
- // Gets the number of tests that should run.
- int test_to_run_count() const;
-
- // Gets the time of the test program start, in ms from the start of the
- // UNIX epoch.
- TimeInMillis start_timestamp() const { return start_timestamp_; }
-
- // Gets the elapsed time, in milliseconds.
- TimeInMillis elapsed_time() const { return elapsed_time_; }
-
- // Returns true if and only if the unit test passed (i.e. all test suites
- // passed).
- bool Passed() const { return !Failed(); }
-
- // Returns true if and only if the unit test failed (i.e. some test suite
- // failed or something outside of all tests failed).
- bool Failed() const {
- return failed_test_suite_count() > 0 || ad_hoc_test_result()->Failed();
- }
-
- // Gets the i-th test suite among all the test suites. i can range from 0 to
- // total_test_suite_count() - 1. If i is not in that range, returns NULL.
- const TestSuite* GetTestSuite(int i) const {
- const int index = GetElementOr(test_suite_indices_, i, -1);
- return index < 0 ? nullptr : test_suites_[static_cast<size_t>(i)];
- }
-
- // Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- const TestCase* GetTestCase(int i) const { return GetTestSuite(i); }
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Gets the i-th test suite among all the test suites. i can range from 0 to
- // total_test_suite_count() - 1. If i is not in that range, returns NULL.
- TestSuite* GetMutableSuiteCase(int i) {
- const int index = GetElementOr(test_suite_indices_, i, -1);
- return index < 0 ? nullptr : test_suites_[static_cast<size_t>(index)];
- }
-
- // Provides access to the event listener list.
- TestEventListeners* listeners() { return &listeners_; }
-
- // Returns the TestResult for the test that's currently running, or
- // the TestResult for the ad hoc test if no test is running.
- TestResult* current_test_result();
-
- // Returns the TestResult for the ad hoc test.
- const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
-
- // Sets the OS stack trace getter.
- //
- // Does nothing if the input and the current OS stack trace getter
- // are the same; otherwise, deletes the old getter and makes the
- // input the current getter.
- void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
-
- // Returns the current OS stack trace getter if it is not NULL;
- // otherwise, creates an OsStackTraceGetter, makes it the current
- // getter, and returns it.
- OsStackTraceGetterInterface* os_stack_trace_getter();
-
- // Returns the current OS stack trace as an std::string.
- //
- // The maximum number of stack frames to be included is specified by
- // the gtest_stack_trace_depth flag. The skip_count parameter
- // specifies the number of top frames to be skipped, which doesn't
- // count against the number of frames to be included.
- //
- // For example, if Foo() calls Bar(), which in turn calls
- // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
- // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
- std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
-
- // Finds and returns a TestSuite with the given name. If one doesn't
- // exist, creates one and returns it.
- //
- // Arguments:
- //
- // test_suite_name: name of the test suite
- // type_param: the name of the test's type parameter, or NULL if
- // this is not a typed or a type-parameterized test.
- // set_up_tc: pointer to the function that sets up the test suite
- // tear_down_tc: pointer to the function that tears down the test suite
- TestSuite* GetTestSuite(const char* test_suite_name, const char* type_param,
- internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc);
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- TestCase* GetTestCase(const char* test_case_name, const char* type_param,
- internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc) {
- return GetTestSuite(test_case_name, type_param, set_up_tc, tear_down_tc);
- }
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // Adds a TestInfo to the unit test.
- //
- // Arguments:
- //
- // set_up_tc: pointer to the function that sets up the test suite
- // tear_down_tc: pointer to the function that tears down the test suite
- // test_info: the TestInfo object
- void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc,
- TestInfo* test_info) {
- // In order to support thread-safe death tests, we need to
- // remember the original working directory when the test program
- // was first invoked. We cannot do this in RUN_ALL_TESTS(), as
- // the user may have changed the current directory before calling
- // RUN_ALL_TESTS(). Therefore we capture the current directory in
- // AddTestInfo(), which is called to register a TEST or TEST_F
- // before main() is reached.
- if (original_working_dir_.IsEmpty()) {
- original_working_dir_.Set(FilePath::GetCurrentDir());
- GTEST_CHECK_(!original_working_dir_.IsEmpty())
- << "Failed to get the current working directory.";
- }
-
- GetTestSuite(test_info->test_suite_name(), test_info->type_param(),
- set_up_tc, tear_down_tc)
- ->AddTestInfo(test_info);
- }
-
- // Returns ParameterizedTestSuiteRegistry object used to keep track of
- // value-parameterized tests and instantiate and register them.
- internal::ParameterizedTestSuiteRegistry& parameterized_test_registry() {
- return parameterized_test_registry_;
- }
-
- // Sets the TestSuite object for the test that's currently running.
- void set_current_test_suite(TestSuite* a_current_test_suite) {
- current_test_suite_ = a_current_test_suite;
- }
-
- // Sets the TestInfo object for the test that's currently running. If
- // current_test_info is NULL, the assertion results will be stored in
- // ad_hoc_test_result_.
- void set_current_test_info(TestInfo* a_current_test_info) {
- current_test_info_ = a_current_test_info;
- }
-
- // Registers all parameterized tests defined using TEST_P and
- // INSTANTIATE_TEST_SUITE_P, creating regular tests for each test/parameter
- // combination. This method can be called more then once; it has guards
- // protecting from registering the tests more then once. If
- // value-parameterized tests are disabled, RegisterParameterizedTests is
- // present but does nothing.
- void RegisterParameterizedTests();
-
- // Runs all tests in this UnitTest object, prints the result, and
- // returns true if all tests are successful. If any exception is
- // thrown during a test, this test is considered to be failed, but
- // the rest of the tests will still be run.
- bool RunAllTests();
-
- // Clears the results of all tests, except the ad hoc tests.
- void ClearNonAdHocTestResult() {
- ForEach(test_suites_, TestSuite::ClearTestSuiteResult);
- }
-
- // Clears the results of ad-hoc test assertions.
- void ClearAdHocTestResult() {
- ad_hoc_test_result_.Clear();
- }
-
- // Adds a TestProperty to the current TestResult object when invoked in a
- // context of a test or a test suite, or to the global property set. If the
- // result already contains a property with the same key, the value will be
- // updated.
- void RecordProperty(const TestProperty& test_property);
-
- enum ReactionToSharding {
- HONOR_SHARDING_PROTOCOL,
- IGNORE_SHARDING_PROTOCOL
- };
-
- // Matches the full name of each test against the user-specified
- // filter to decide whether the test should run, then records the
- // result in each TestSuite and TestInfo object.
- // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
- // based on sharding variables in the environment.
- // Returns the number of tests that should run.
- int FilterTests(ReactionToSharding shard_tests);
-
- // Prints the names of the tests matching the user-specified filter flag.
- void ListTestsMatchingFilter();
-
- const TestSuite* current_test_suite() const { return current_test_suite_; }
- TestInfo* current_test_info() { return current_test_info_; }
- const TestInfo* current_test_info() const { return current_test_info_; }
-
- // Returns the vector of environments that need to be set-up/torn-down
- // before/after the tests are run.
- std::vector<Environment*>& environments() { return environments_; }
-
- // Getters for the per-thread Google Test trace stack.
- std::vector<TraceInfo>& gtest_trace_stack() {
- return *(gtest_trace_stack_.pointer());
- }
- const std::vector<TraceInfo>& gtest_trace_stack() const {
- return gtest_trace_stack_.get();
- }
-
-#if GTEST_HAS_DEATH_TEST
- void InitDeathTestSubprocessControlInfo() {
- internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
- }
- // Returns a pointer to the parsed --gtest_internal_run_death_test
- // flag, or NULL if that flag was not specified.
- // This information is useful only in a death test child process.
- // Must not be called before a call to InitGoogleTest.
- const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
- return internal_run_death_test_flag_.get();
- }
-
- // Returns a pointer to the current death test factory.
- internal::DeathTestFactory* death_test_factory() {
- return death_test_factory_.get();
- }
-
- void SuppressTestEventsIfInSubprocess();
-
- friend class ReplaceDeathTestFactory;
-#endif // GTEST_HAS_DEATH_TEST
-
- // Initializes the event listener performing XML output as specified by
- // UnitTestOptions. Must not be called before InitGoogleTest.
- void ConfigureXmlOutput();
-
-#if GTEST_CAN_STREAM_RESULTS_
- // Initializes the event listener for streaming test results to a socket.
- // Must not be called before InitGoogleTest.
- void ConfigureStreamingOutput();
-#endif
-
- // Performs initialization dependent upon flag values obtained in
- // ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
- // ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
- // this function is also called from RunAllTests. Since this function can be
- // called more than once, it has to be idempotent.
- void PostFlagParsingInit();
-
- // Gets the random seed used at the start of the current test iteration.
- int random_seed() const { return random_seed_; }
-
- // Gets the random number generator.
- internal::Random* random() { return &random_; }
-
- // Shuffles all test suites, and the tests within each test suite,
- // making sure that death tests are still run first.
- void ShuffleTests();
-
- // Restores the test suites and tests to their order before the first shuffle.
- void UnshuffleTests();
-
- // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
- // UnitTest::Run() starts.
- bool catch_exceptions() const { return catch_exceptions_; }
-
- private:
- friend class ::testing::UnitTest;
-
- // Used by UnitTest::Run() to capture the state of
- // GTEST_FLAG(catch_exceptions) at the moment it starts.
- void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
-
- // The UnitTest object that owns this implementation object.
- UnitTest* const parent_;
-
- // The working directory when the first TEST() or TEST_F() was
- // executed.
- internal::FilePath original_working_dir_;
-
- // The default test part result reporters.
- DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
- DefaultPerThreadTestPartResultReporter
- default_per_thread_test_part_result_reporter_;
-
- // Points to (but doesn't own) the global test part result reporter.
- TestPartResultReporterInterface* global_test_part_result_repoter_;
-
- // Protects read and write access to global_test_part_result_reporter_.
- internal::Mutex global_test_part_result_reporter_mutex_;
-
- // Points to (but doesn't own) the per-thread test part result reporter.
- internal::ThreadLocal<TestPartResultReporterInterface*>
- per_thread_test_part_result_reporter_;
-
- // The vector of environments that need to be set-up/torn-down
- // before/after the tests are run.
- std::vector<Environment*> environments_;
-
- // The vector of TestSuites in their original order. It owns the
- // elements in the vector.
- std::vector<TestSuite*> test_suites_;
-
- // Provides a level of indirection for the test suite list to allow
- // easy shuffling and restoring the test suite order. The i-th
- // element of this vector is the index of the i-th test suite in the
- // shuffled order.
- std::vector<int> test_suite_indices_;
-
- // ParameterizedTestRegistry object used to register value-parameterized
- // tests.
- internal::ParameterizedTestSuiteRegistry parameterized_test_registry_;
-
- // Indicates whether RegisterParameterizedTests() has been called already.
- bool parameterized_tests_registered_;
-
- // Index of the last death test suite registered. Initially -1.
- int last_death_test_suite_;
-
- // This points to the TestSuite for the currently running test. It
- // changes as Google Test goes through one test suite after another.
- // When no test is running, this is set to NULL and Google Test
- // stores assertion results in ad_hoc_test_result_. Initially NULL.
- TestSuite* current_test_suite_;
-
- // This points to the TestInfo for the currently running test. It
- // changes as Google Test goes through one test after another. When
- // no test is running, this is set to NULL and Google Test stores
- // assertion results in ad_hoc_test_result_. Initially NULL.
- TestInfo* current_test_info_;
-
- // Normally, a user only writes assertions inside a TEST or TEST_F,
- // or inside a function called by a TEST or TEST_F. Since Google
- // Test keeps track of which test is current running, it can
- // associate such an assertion with the test it belongs to.
- //
- // If an assertion is encountered when no TEST or TEST_F is running,
- // Google Test attributes the assertion result to an imaginary "ad hoc"
- // test, and records the result in ad_hoc_test_result_.
- TestResult ad_hoc_test_result_;
-
- // The list of event listeners that can be used to track events inside
- // Google Test.
- TestEventListeners listeners_;
-
- // The OS stack trace getter. Will be deleted when the UnitTest
- // object is destructed. By default, an OsStackTraceGetter is used,
- // but the user can set this field to use a custom getter if that is
- // desired.
- OsStackTraceGetterInterface* os_stack_trace_getter_;
-
- // True if and only if PostFlagParsingInit() has been called.
- bool post_flag_parse_init_performed_;
-
- // The random number seed used at the beginning of the test run.
- int random_seed_;
-
- // Our random number generator.
- internal::Random random_;
-
- // The time of the test program start, in ms from the start of the
- // UNIX epoch.
- TimeInMillis start_timestamp_;
-
- // How long the test took to run, in milliseconds.
- TimeInMillis elapsed_time_;
-
-#if GTEST_HAS_DEATH_TEST
- // The decomposed components of the gtest_internal_run_death_test flag,
- // parsed when RUN_ALL_TESTS is called.
- std::unique_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
- std::unique_ptr<internal::DeathTestFactory> death_test_factory_;
-#endif // GTEST_HAS_DEATH_TEST
-
- // A per-thread stack of traces created by the SCOPED_TRACE() macro.
- internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
-
- // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
- // starts.
- bool catch_exceptions_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
-}; // class UnitTestImpl
-
-// Convenience function for accessing the global UnitTest
-// implementation object.
-inline UnitTestImpl* GetUnitTestImpl() {
- return UnitTest::GetInstance()->impl();
-}
-
-#if GTEST_USES_SIMPLE_RE
-
-// Internal helper functions for implementing the simple regular
-// expression matcher.
-GTEST_API_ bool IsInSet(char ch, const char* str);
-GTEST_API_ bool IsAsciiDigit(char ch);
-GTEST_API_ bool IsAsciiPunct(char ch);
-GTEST_API_ bool IsRepeat(char ch);
-GTEST_API_ bool IsAsciiWhiteSpace(char ch);
-GTEST_API_ bool IsAsciiWordChar(char ch);
-GTEST_API_ bool IsValidEscape(char ch);
-GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
-GTEST_API_ bool ValidateRegex(const char* regex);
-GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
-GTEST_API_ bool MatchRepetitionAndRegexAtHead(
- bool escaped, char ch, char repeat, const char* regex, const char* str);
-GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
-
-#endif // GTEST_USES_SIMPLE_RE
-
-// Parses the command line for Google Test flags, without initializing
-// other parts of Google Test.
-GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
-GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
-
-#if GTEST_HAS_DEATH_TEST
-
-// Returns the message describing the last system error, regardless of the
-// platform.
-GTEST_API_ std::string GetLastErrnoDescription();
-
-// Attempts to parse a string into a positive integer pointed to by the
-// number parameter. Returns true if that is possible.
-// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
-// it here.
-template <typename Integer>
-bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
- // Fail fast if the given string does not begin with a digit;
- // this bypasses strtoXXX's "optional leading whitespace and plus
- // or minus sign" semantics, which are undesirable here.
- if (str.empty() || !IsDigit(str[0])) {
- return false;
- }
- errno = 0;
-
- char* end;
- // BiggestConvertible is the largest integer type that system-provided
- // string-to-number conversion routines can return.
-
-# if GTEST_OS_WINDOWS && !defined(__GNUC__)
-
- // MSVC and C++ Builder define __int64 instead of the standard long long.
- typedef unsigned __int64 BiggestConvertible;
- const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
-
-# else
-
- typedef unsigned long long BiggestConvertible; // NOLINT
- const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
-
-# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
-
- const bool parse_success = *end == '\0' && errno == 0;
-
- GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
-
- const Integer result = static_cast<Integer>(parsed);
- if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
- *number = result;
- return true;
- }
- return false;
-}
-#endif // GTEST_HAS_DEATH_TEST
-
-// TestResult contains some private methods that should be hidden from
-// Google Test user but are required for testing. This class allow our tests
-// to access them.
-//
-// This class is supplied only for the purpose of testing Google Test's own
-// constructs. Do not use it in user tests, either directly or indirectly.
-class TestResultAccessor {
- public:
- static void RecordProperty(TestResult* test_result,
- const std::string& xml_element,
- const TestProperty& property) {
- test_result->RecordProperty(xml_element, property);
- }
-
- static void ClearTestPartResults(TestResult* test_result) {
- test_result->ClearTestPartResults();
- }
-
- static const std::vector<testing::TestPartResult>& test_part_results(
- const TestResult& test_result) {
- return test_result.test_part_results();
- }
-};
-
-#if GTEST_CAN_STREAM_RESULTS_
-
-// Streams test results to the given port on the given host machine.
-class StreamingListener : public EmptyTestEventListener {
- public:
- // Abstract base class for writing strings to a socket.
- class AbstractSocketWriter {
- public:
- virtual ~AbstractSocketWriter() {}
-
- // Sends a string to the socket.
- virtual void Send(const std::string& message) = 0;
-
- // Closes the socket.
- virtual void CloseConnection() {}
-
- // Sends a string and a newline to the socket.
- void SendLn(const std::string& message) { Send(message + "\n"); }
- };
-
- // Concrete class for actually writing strings to a socket.
- class SocketWriter : public AbstractSocketWriter {
- public:
- SocketWriter(const std::string& host, const std::string& port)
- : sockfd_(-1), host_name_(host), port_num_(port) {
- MakeConnection();
- }
-
- ~SocketWriter() override {
- if (sockfd_ != -1)
- CloseConnection();
- }
-
- // Sends a string to the socket.
- void Send(const std::string& message) override {
- GTEST_CHECK_(sockfd_ != -1)
- << "Send() can be called only when there is a connection.";
-
- const auto len = static_cast<size_t>(message.length());
- if (write(sockfd_, message.c_str(), len) != static_cast<ssize_t>(len)) {
- GTEST_LOG_(WARNING)
- << "stream_result_to: failed to stream to "
- << host_name_ << ":" << port_num_;
- }
- }
-
- private:
- // Creates a client socket and connects to the server.
- void MakeConnection();
-
- // Closes the socket.
- void CloseConnection() override {
- GTEST_CHECK_(sockfd_ != -1)
- << "CloseConnection() can be called only when there is a connection.";
-
- close(sockfd_);
- sockfd_ = -1;
- }
-
- int sockfd_; // socket file descriptor
- const std::string host_name_;
- const std::string port_num_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
- }; // class SocketWriter
-
- // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
- static std::string UrlEncode(const char* str);
-
- StreamingListener(const std::string& host, const std::string& port)
- : socket_writer_(new SocketWriter(host, port)) {
- Start();
- }
-
- explicit StreamingListener(AbstractSocketWriter* socket_writer)
- : socket_writer_(socket_writer) { Start(); }
-
- void OnTestProgramStart(const UnitTest& /* unit_test */) override {
- SendLn("event=TestProgramStart");
- }
-
- void OnTestProgramEnd(const UnitTest& unit_test) override {
- // Note that Google Test current only report elapsed time for each
- // test iteration, not for the entire test program.
- SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
-
- // Notify the streaming server to stop.
- socket_writer_->CloseConnection();
- }
-
- void OnTestIterationStart(const UnitTest& /* unit_test */,
- int iteration) override {
- SendLn("event=TestIterationStart&iteration=" +
- StreamableToString(iteration));
- }
-
- void OnTestIterationEnd(const UnitTest& unit_test,
- int /* iteration */) override {
- SendLn("event=TestIterationEnd&passed=" +
- FormatBool(unit_test.Passed()) + "&elapsed_time=" +
- StreamableToString(unit_test.elapsed_time()) + "ms");
- }
-
- // Note that "event=TestCaseStart" is a wire format and has to remain
- // "case" for compatibilty
- void OnTestCaseStart(const TestCase& test_case) override {
- SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
- }
-
- // Note that "event=TestCaseEnd" is a wire format and has to remain
- // "case" for compatibilty
- void OnTestCaseEnd(const TestCase& test_case) override {
- SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed()) +
- "&elapsed_time=" + StreamableToString(test_case.elapsed_time()) +
- "ms");
- }
-
- void OnTestStart(const TestInfo& test_info) override {
- SendLn(std::string("event=TestStart&name=") + test_info.name());
- }
-
- void OnTestEnd(const TestInfo& test_info) override {
- SendLn("event=TestEnd&passed=" +
- FormatBool((test_info.result())->Passed()) +
- "&elapsed_time=" +
- StreamableToString((test_info.result())->elapsed_time()) + "ms");
- }
-
- void OnTestPartResult(const TestPartResult& test_part_result) override {
- const char* file_name = test_part_result.file_name();
- if (file_name == nullptr) file_name = "";
- SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
- "&line=" + StreamableToString(test_part_result.line_number()) +
- "&message=" + UrlEncode(test_part_result.message()));
- }
-
- private:
- // Sends the given message and a newline to the socket.
- void SendLn(const std::string& message) { socket_writer_->SendLn(message); }
-
- // Called at the start of streaming to notify the receiver what
- // protocol we are using.
- void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
-
- std::string FormatBool(bool value) { return value ? "1" : "0"; }
-
- const std::unique_ptr<AbstractSocketWriter> socket_writer_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
-}; // class StreamingListener
-
-#endif // GTEST_CAN_STREAM_RESULTS_
-
-} // namespace internal
-} // namespace testing
-
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
-
-#endif // GTEST_SRC_GTEST_INTERNAL_INL_H_
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This file implements just enough of the matcher interface to allow
-// EXPECT_DEATH and friends to accept a matcher argument.
-
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-port.h"
-#include "gtest/gtest-matchers.h"
-
-#include <string>
-
-namespace testing {
-
-// Constructs a matcher that matches a const std::string& whose value is
-// equal to s.
-Matcher<const std::string&>::Matcher(const std::string& s) { *this = Eq(s); }
-
-// Constructs a matcher that matches a const std::string& whose value is
-// equal to s.
-Matcher<const std::string&>::Matcher(const char* s) {
- *this = Eq(std::string(s));
-}
-
-// Constructs a matcher that matches a std::string whose value is equal to
-// s.
-Matcher<std::string>::Matcher(const std::string& s) { *this = Eq(s); }
-
-// Constructs a matcher that matches a std::string whose value is equal to
-// s.
-Matcher<std::string>::Matcher(const char* s) { *this = Eq(std::string(s)); }
-
-#if GTEST_HAS_ABSL
-// Constructs a matcher that matches a const absl::string_view& whose value is
-// equal to s.
-Matcher<const absl::string_view&>::Matcher(const std::string& s) {
- *this = Eq(s);
-}
-
-// Constructs a matcher that matches a const absl::string_view& whose value is
-// equal to s.
-Matcher<const absl::string_view&>::Matcher(const char* s) {
- *this = Eq(std::string(s));
-}
-
-// Constructs a matcher that matches a const absl::string_view& whose value is
-// equal to s.
-Matcher<const absl::string_view&>::Matcher(absl::string_view s) {
- *this = Eq(std::string(s));
-}
-
-// Constructs a matcher that matches a absl::string_view whose value is equal to
-// s.
-Matcher<absl::string_view>::Matcher(const std::string& s) { *this = Eq(s); }
-
-// Constructs a matcher that matches a absl::string_view whose value is equal to
-// s.
-Matcher<absl::string_view>::Matcher(const char* s) {
- *this = Eq(std::string(s));
-}
-
-// Constructs a matcher that matches a absl::string_view whose value is equal to
-// s.
-Matcher<absl::string_view>::Matcher(absl::string_view s) {
- *this = Eq(std::string(s));
-}
-#endif // GTEST_HAS_ABSL
-
-} // namespace testing
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "gtest/internal/gtest-port.h"
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fstream>
-#include <memory>
-
-#if GTEST_OS_WINDOWS
-# include <windows.h>
-# include <io.h>
-# include <sys/stat.h>
-# include <map> // Used in ThreadLocal.
-# ifdef _MSC_VER
-# include <crtdbg.h>
-# endif // _MSC_VER
-#else
-# include <unistd.h>
-#endif // GTEST_OS_WINDOWS
-
-#if GTEST_OS_MAC
-# include <mach/mach_init.h>
-# include <mach/task.h>
-# include <mach/vm_map.h>
-#endif // GTEST_OS_MAC
-
-#if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
- GTEST_OS_NETBSD || GTEST_OS_OPENBSD
-# include <sys/sysctl.h>
-# if GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
-# include <sys/user.h>
-# endif
-#endif
-
-#if GTEST_OS_QNX
-# include <devctl.h>
-# include <fcntl.h>
-# include <sys/procfs.h>
-#endif // GTEST_OS_QNX
-
-#if GTEST_OS_AIX
-# include <procinfo.h>
-# include <sys/types.h>
-#endif // GTEST_OS_AIX
-
-#if GTEST_OS_FUCHSIA
-# include <zircon/process.h>
-# include <zircon/syscalls.h>
-#endif // GTEST_OS_FUCHSIA
-
-#include "gtest/gtest-spi.h"
-#include "gtest/gtest-message.h"
-#include "gtest/internal/gtest-internal.h"
-#include "gtest/internal/gtest-string.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-namespace internal {
-
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
-const int kStdOutFileno = 1;
-const int kStdErrFileno = 2;
-#else
-const int kStdOutFileno = STDOUT_FILENO;
-const int kStdErrFileno = STDERR_FILENO;
-#endif // _MSC_VER
-
-#if GTEST_OS_LINUX
-
-namespace {
-template <typename T>
-T ReadProcFileField(const std::string& filename, int field) {
- std::string dummy;
- std::ifstream file(filename.c_str());
- while (field-- > 0) {
- file >> dummy;
- }
- T output = 0;
- file >> output;
- return output;
-}
-} // namespace
-
-// Returns the number of active threads, or 0 when there is an error.
-size_t GetThreadCount() {
- const std::string filename =
- (Message() << "/proc/" << getpid() << "/stat").GetString();
- return ReadProcFileField<size_t>(filename, 19);
-}
-
-#elif GTEST_OS_MAC
-
-size_t GetThreadCount() {
- const task_t task = mach_task_self();
- mach_msg_type_number_t thread_count;
- thread_act_array_t thread_list;
- const kern_return_t status = task_threads(task, &thread_list, &thread_count);
- if (status == KERN_SUCCESS) {
- // task_threads allocates resources in thread_list and we need to free them
- // to avoid leaks.
- vm_deallocate(task,
- reinterpret_cast<vm_address_t>(thread_list),
- sizeof(thread_t) * thread_count);
- return static_cast<size_t>(thread_count);
- } else {
- return 0;
- }
-}
-
-#elif GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
- GTEST_OS_NETBSD
-
-#if GTEST_OS_NETBSD
-#undef KERN_PROC
-#define KERN_PROC KERN_PROC2
-#define kinfo_proc kinfo_proc2
-#endif
-
-#if GTEST_OS_DRAGONFLY
-#define KP_NLWP(kp) (kp.kp_nthreads)
-#elif GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD
-#define KP_NLWP(kp) (kp.ki_numthreads)
-#elif GTEST_OS_NETBSD
-#define KP_NLWP(kp) (kp.p_nlwps)
-#endif
-
-// Returns the number of threads running in the process, or 0 to indicate that
-// we cannot detect it.
-size_t GetThreadCount() {
- int mib[] = {
- CTL_KERN,
- KERN_PROC,
- KERN_PROC_PID,
- getpid(),
-#if GTEST_OS_NETBSD
- sizeof(struct kinfo_proc),
- 1,
-#endif
- };
- u_int miblen = sizeof(mib) / sizeof(mib[0]);
- struct kinfo_proc info;
- size_t size = sizeof(info);
- if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
- return 0;
- }
- return static_cast<size_t>(KP_NLWP(info));
-}
-#elif GTEST_OS_OPENBSD
-
-// Returns the number of threads running in the process, or 0 to indicate that
-// we cannot detect it.
-size_t GetThreadCount() {
- int mib[] = {
- CTL_KERN,
- KERN_PROC,
- KERN_PROC_PID | KERN_PROC_SHOW_THREADS,
- getpid(),
- sizeof(struct kinfo_proc),
- 0,
- };
- u_int miblen = sizeof(mib) / sizeof(mib[0]);
-
- // get number of structs
- size_t size;
- if (sysctl(mib, miblen, NULL, &size, NULL, 0)) {
- return 0;
- }
- mib[5] = size / mib[4];
-
- // populate array of structs
- struct kinfo_proc info[mib[5]];
- if (sysctl(mib, miblen, &info, &size, NULL, 0)) {
- return 0;
- }
-
- // exclude empty members
- int nthreads = 0;
- for (int i = 0; i < size / mib[4]; i++) {
- if (info[i].p_tid != -1)
- nthreads++;
- }
- return nthreads;
-}
-
-#elif GTEST_OS_QNX
-
-// Returns the number of threads running in the process, or 0 to indicate that
-// we cannot detect it.
-size_t GetThreadCount() {
- const int fd = open("/proc/self/as", O_RDONLY);
- if (fd < 0) {
- return 0;
- }
- procfs_info process_info;
- const int status =
- devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), nullptr);
- close(fd);
- if (status == EOK) {
- return static_cast<size_t>(process_info.num_threads);
- } else {
- return 0;
- }
-}
-
-#elif GTEST_OS_AIX
-
-size_t GetThreadCount() {
- struct procentry64 entry;
- pid_t pid = getpid();
- int status = getprocs64(&entry, sizeof(entry), nullptr, 0, &pid, 1);
- if (status == 1) {
- return entry.pi_thcount;
- } else {
- return 0;
- }
-}
-
-#elif GTEST_OS_FUCHSIA
-
-size_t GetThreadCount() {
- int dummy_buffer;
- size_t avail;
- zx_status_t status = zx_object_get_info(
- zx_process_self(),
- ZX_INFO_PROCESS_THREADS,
- &dummy_buffer,
- 0,
- nullptr,
- &avail);
- if (status == ZX_OK) {
- return avail;
- } else {
- return 0;
- }
-}
-
-#else
-
-size_t GetThreadCount() {
- // There's no portable way to detect the number of threads, so we just
- // return 0 to indicate that we cannot detect it.
- return 0;
-}
-
-#endif // GTEST_OS_LINUX
-
-#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
-
-void SleepMilliseconds(int n) {
- ::Sleep(static_cast<DWORD>(n));
-}
-
-AutoHandle::AutoHandle()
- : handle_(INVALID_HANDLE_VALUE) {}
-
-AutoHandle::AutoHandle(Handle handle)
- : handle_(handle) {}
-
-AutoHandle::~AutoHandle() {
- Reset();
-}
-
-AutoHandle::Handle AutoHandle::Get() const {
- return handle_;
-}
-
-void AutoHandle::Reset() {
- Reset(INVALID_HANDLE_VALUE);
-}
-
-void AutoHandle::Reset(HANDLE handle) {
- // Resetting with the same handle we already own is invalid.
- if (handle_ != handle) {
- if (IsCloseable()) {
- ::CloseHandle(handle_);
- }
- handle_ = handle;
- } else {
- GTEST_CHECK_(!IsCloseable())
- << "Resetting a valid handle to itself is likely a programmer error "
- "and thus not allowed.";
- }
-}
-
-bool AutoHandle::IsCloseable() const {
- // Different Windows APIs may use either of these values to represent an
- // invalid handle.
- return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE;
-}
-
-Notification::Notification()
- : event_(::CreateEvent(nullptr, // Default security attributes.
- TRUE, // Do not reset automatically.
- FALSE, // Initially unset.
- nullptr)) { // Anonymous event.
- GTEST_CHECK_(event_.Get() != nullptr);
-}
-
-void Notification::Notify() {
- GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
-}
-
-void Notification::WaitForNotification() {
- GTEST_CHECK_(
- ::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
-}
-
-Mutex::Mutex()
- : owner_thread_id_(0),
- type_(kDynamic),
- critical_section_init_phase_(0),
- critical_section_(new CRITICAL_SECTION) {
- ::InitializeCriticalSection(critical_section_);
-}
-
-Mutex::~Mutex() {
- // Static mutexes are leaked intentionally. It is not thread-safe to try
- // to clean them up.
- if (type_ == kDynamic) {
- ::DeleteCriticalSection(critical_section_);
- delete critical_section_;
- critical_section_ = nullptr;
- }
-}
-
-void Mutex::Lock() {
- ThreadSafeLazyInit();
- ::EnterCriticalSection(critical_section_);
- owner_thread_id_ = ::GetCurrentThreadId();
-}
-
-void Mutex::Unlock() {
- ThreadSafeLazyInit();
- // We don't protect writing to owner_thread_id_ here, as it's the
- // caller's responsibility to ensure that the current thread holds the
- // mutex when this is called.
- owner_thread_id_ = 0;
- ::LeaveCriticalSection(critical_section_);
-}
-
-// Does nothing if the current thread holds the mutex. Otherwise, crashes
-// with high probability.
-void Mutex::AssertHeld() {
- ThreadSafeLazyInit();
- GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
- << "The current thread is not holding the mutex @" << this;
-}
-
-namespace {
-
-#ifdef _MSC_VER
-// Use the RAII idiom to flag mem allocs that are intentionally never
-// deallocated. The motivation is to silence the false positive mem leaks
-// that are reported by the debug version of MS's CRT which can only detect
-// if an alloc is missing a matching deallocation.
-// Example:
-// MemoryIsNotDeallocated memory_is_not_deallocated;
-// critical_section_ = new CRITICAL_SECTION;
-//
-class MemoryIsNotDeallocated
-{
- public:
- MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
- old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
- // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
- // doesn't report mem leak if there's no matching deallocation.
- _CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
- }
-
- ~MemoryIsNotDeallocated() {
- // Restore the original _CRTDBG_ALLOC_MEM_DF flag
- _CrtSetDbgFlag(old_crtdbg_flag_);
- }
-
- private:
- int old_crtdbg_flag_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
-};
-#endif // _MSC_VER
-
-} // namespace
-
-// Initializes owner_thread_id_ and critical_section_ in static mutexes.
-void Mutex::ThreadSafeLazyInit() {
- // Dynamic mutexes are initialized in the constructor.
- if (type_ == kStatic) {
- switch (
- ::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
- case 0:
- // If critical_section_init_phase_ was 0 before the exchange, we
- // are the first to test it and need to perform the initialization.
- owner_thread_id_ = 0;
- {
- // Use RAII to flag that following mem alloc is never deallocated.
-#ifdef _MSC_VER
- MemoryIsNotDeallocated memory_is_not_deallocated;
-#endif // _MSC_VER
- critical_section_ = new CRITICAL_SECTION;
- }
- ::InitializeCriticalSection(critical_section_);
- // Updates the critical_section_init_phase_ to 2 to signal
- // initialization complete.
- GTEST_CHECK_(::InterlockedCompareExchange(
- &critical_section_init_phase_, 2L, 1L) ==
- 1L);
- break;
- case 1:
- // Somebody else is already initializing the mutex; spin until they
- // are done.
- while (::InterlockedCompareExchange(&critical_section_init_phase_,
- 2L,
- 2L) != 2L) {
- // Possibly yields the rest of the thread's time slice to other
- // threads.
- ::Sleep(0);
- }
- break;
-
- case 2:
- break; // The mutex is already initialized and ready for use.
-
- default:
- GTEST_CHECK_(false)
- << "Unexpected value of critical_section_init_phase_ "
- << "while initializing a static mutex.";
- }
- }
-}
-
-namespace {
-
-class ThreadWithParamSupport : public ThreadWithParamBase {
- public:
- static HANDLE CreateThread(Runnable* runnable,
- Notification* thread_can_start) {
- ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
- DWORD thread_id;
- HANDLE thread_handle = ::CreateThread(
- nullptr, // Default security.
- 0, // Default stack size.
- &ThreadWithParamSupport::ThreadMain,
- param, // Parameter to ThreadMainStatic
- 0x0, // Default creation flags.
- &thread_id); // Need a valid pointer for the call to work under Win98.
- GTEST_CHECK_(thread_handle != nullptr)
- << "CreateThread failed with error " << ::GetLastError() << ".";
- if (thread_handle == nullptr) {
- delete param;
- }
- return thread_handle;
- }
-
- private:
- struct ThreadMainParam {
- ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
- : runnable_(runnable),
- thread_can_start_(thread_can_start) {
- }
- std::unique_ptr<Runnable> runnable_;
- // Does not own.
- Notification* thread_can_start_;
- };
-
- static DWORD WINAPI ThreadMain(void* ptr) {
- // Transfers ownership.
- std::unique_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
- if (param->thread_can_start_ != nullptr)
- param->thread_can_start_->WaitForNotification();
- param->runnable_->Run();
- return 0;
- }
-
- // Prohibit instantiation.
- ThreadWithParamSupport();
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
-};
-
-} // namespace
-
-ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
- Notification* thread_can_start)
- : thread_(ThreadWithParamSupport::CreateThread(runnable,
- thread_can_start)) {
-}
-
-ThreadWithParamBase::~ThreadWithParamBase() {
- Join();
-}
-
-void ThreadWithParamBase::Join() {
- GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
- << "Failed to join the thread with error " << ::GetLastError() << ".";
-}
-
-// Maps a thread to a set of ThreadIdToThreadLocals that have values
-// instantiated on that thread and notifies them when the thread exits. A
-// ThreadLocal instance is expected to persist until all threads it has
-// values on have terminated.
-class ThreadLocalRegistryImpl {
- public:
- // Registers thread_local_instance as having value on the current thread.
- // Returns a value that can be used to identify the thread from other threads.
- static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
- const ThreadLocalBase* thread_local_instance) {
- DWORD current_thread = ::GetCurrentThreadId();
- MutexLock lock(&mutex_);
- ThreadIdToThreadLocals* const thread_to_thread_locals =
- GetThreadLocalsMapLocked();
- ThreadIdToThreadLocals::iterator thread_local_pos =
- thread_to_thread_locals->find(current_thread);
- if (thread_local_pos == thread_to_thread_locals->end()) {
- thread_local_pos = thread_to_thread_locals->insert(
- std::make_pair(current_thread, ThreadLocalValues())).first;
- StartWatcherThreadFor(current_thread);
- }
- ThreadLocalValues& thread_local_values = thread_local_pos->second;
- ThreadLocalValues::iterator value_pos =
- thread_local_values.find(thread_local_instance);
- if (value_pos == thread_local_values.end()) {
- value_pos =
- thread_local_values
- .insert(std::make_pair(
- thread_local_instance,
- std::shared_ptr<ThreadLocalValueHolderBase>(
- thread_local_instance->NewValueForCurrentThread())))
- .first;
- }
- return value_pos->second.get();
- }
-
- static void OnThreadLocalDestroyed(
- const ThreadLocalBase* thread_local_instance) {
- std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
- // Clean up the ThreadLocalValues data structure while holding the lock, but
- // defer the destruction of the ThreadLocalValueHolderBases.
- {
- MutexLock lock(&mutex_);
- ThreadIdToThreadLocals* const thread_to_thread_locals =
- GetThreadLocalsMapLocked();
- for (ThreadIdToThreadLocals::iterator it =
- thread_to_thread_locals->begin();
- it != thread_to_thread_locals->end();
- ++it) {
- ThreadLocalValues& thread_local_values = it->second;
- ThreadLocalValues::iterator value_pos =
- thread_local_values.find(thread_local_instance);
- if (value_pos != thread_local_values.end()) {
- value_holders.push_back(value_pos->second);
- thread_local_values.erase(value_pos);
- // This 'if' can only be successful at most once, so theoretically we
- // could break out of the loop here, but we don't bother doing so.
- }
- }
- }
- // Outside the lock, let the destructor for 'value_holders' deallocate the
- // ThreadLocalValueHolderBases.
- }
-
- static void OnThreadExit(DWORD thread_id) {
- GTEST_CHECK_(thread_id != 0) << ::GetLastError();
- std::vector<std::shared_ptr<ThreadLocalValueHolderBase> > value_holders;
- // Clean up the ThreadIdToThreadLocals data structure while holding the
- // lock, but defer the destruction of the ThreadLocalValueHolderBases.
- {
- MutexLock lock(&mutex_);
- ThreadIdToThreadLocals* const thread_to_thread_locals =
- GetThreadLocalsMapLocked();
- ThreadIdToThreadLocals::iterator thread_local_pos =
- thread_to_thread_locals->find(thread_id);
- if (thread_local_pos != thread_to_thread_locals->end()) {
- ThreadLocalValues& thread_local_values = thread_local_pos->second;
- for (ThreadLocalValues::iterator value_pos =
- thread_local_values.begin();
- value_pos != thread_local_values.end();
- ++value_pos) {
- value_holders.push_back(value_pos->second);
- }
- thread_to_thread_locals->erase(thread_local_pos);
- }
- }
- // Outside the lock, let the destructor for 'value_holders' deallocate the
- // ThreadLocalValueHolderBases.
- }
-
- private:
- // In a particular thread, maps a ThreadLocal object to its value.
- typedef std::map<const ThreadLocalBase*,
- std::shared_ptr<ThreadLocalValueHolderBase> >
- ThreadLocalValues;
- // Stores all ThreadIdToThreadLocals having values in a thread, indexed by
- // thread's ID.
- typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
-
- // Holds the thread id and thread handle that we pass from
- // StartWatcherThreadFor to WatcherThreadFunc.
- typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
-
- static void StartWatcherThreadFor(DWORD thread_id) {
- // The returned handle will be kept in thread_map and closed by
- // watcher_thread in WatcherThreadFunc.
- HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
- FALSE,
- thread_id);
- GTEST_CHECK_(thread != nullptr);
- // We need to pass a valid thread ID pointer into CreateThread for it
- // to work correctly under Win98.
- DWORD watcher_thread_id;
- HANDLE watcher_thread = ::CreateThread(
- nullptr, // Default security.
- 0, // Default stack size
- &ThreadLocalRegistryImpl::WatcherThreadFunc,
- reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
- CREATE_SUSPENDED, &watcher_thread_id);
- GTEST_CHECK_(watcher_thread != nullptr);
- // Give the watcher thread the same priority as ours to avoid being
- // blocked by it.
- ::SetThreadPriority(watcher_thread,
- ::GetThreadPriority(::GetCurrentThread()));
- ::ResumeThread(watcher_thread);
- ::CloseHandle(watcher_thread);
- }
-
- // Monitors exit from a given thread and notifies those
- // ThreadIdToThreadLocals about thread termination.
- static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
- const ThreadIdAndHandle* tah =
- reinterpret_cast<const ThreadIdAndHandle*>(param);
- GTEST_CHECK_(
- ::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
- OnThreadExit(tah->first);
- ::CloseHandle(tah->second);
- delete tah;
- return 0;
- }
-
- // Returns map of thread local instances.
- static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
- mutex_.AssertHeld();
-#ifdef _MSC_VER
- MemoryIsNotDeallocated memory_is_not_deallocated;
-#endif // _MSC_VER
- static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
- return map;
- }
-
- // Protects access to GetThreadLocalsMapLocked() and its return value.
- static Mutex mutex_;
- // Protects access to GetThreadMapLocked() and its return value.
- static Mutex thread_map_mutex_;
-};
-
-Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
-Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
-
-ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
- const ThreadLocalBase* thread_local_instance) {
- return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
- thread_local_instance);
-}
-
-void ThreadLocalRegistry::OnThreadLocalDestroyed(
- const ThreadLocalBase* thread_local_instance) {
- ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
-}
-
-#endif // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
-
-#if GTEST_USES_POSIX_RE
-
-// Implements RE. Currently only needed for death tests.
-
-RE::~RE() {
- if (is_valid_) {
- // regfree'ing an invalid regex might crash because the content
- // of the regex is undefined. Since the regex's are essentially
- // the same, one cannot be valid (or invalid) without the other
- // being so too.
- regfree(&partial_regex_);
- regfree(&full_regex_);
- }
- free(const_cast<char*>(pattern_));
-}
-
-// Returns true if and only if regular expression re matches the entire str.
-bool RE::FullMatch(const char* str, const RE& re) {
- if (!re.is_valid_) return false;
-
- regmatch_t match;
- return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
-}
-
-// Returns true if and only if regular expression re matches a substring of
-// str (including str itself).
-bool RE::PartialMatch(const char* str, const RE& re) {
- if (!re.is_valid_) return false;
-
- regmatch_t match;
- return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
-}
-
-// Initializes an RE from its string representation.
-void RE::Init(const char* regex) {
- pattern_ = posix::StrDup(regex);
-
- // Reserves enough bytes to hold the regular expression used for a
- // full match.
- const size_t full_regex_len = strlen(regex) + 10;
- char* const full_pattern = new char[full_regex_len];
-
- snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
- is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
- // We want to call regcomp(&partial_regex_, ...) even if the
- // previous expression returns false. Otherwise partial_regex_ may
- // not be properly initialized can may cause trouble when it's
- // freed.
- //
- // Some implementation of POSIX regex (e.g. on at least some
- // versions of Cygwin) doesn't accept the empty string as a valid
- // regex. We change it to an equivalent form "()" to be safe.
- if (is_valid_) {
- const char* const partial_regex = (*regex == '\0') ? "()" : regex;
- is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
- }
- EXPECT_TRUE(is_valid_)
- << "Regular expression \"" << regex
- << "\" is not a valid POSIX Extended regular expression.";
-
- delete[] full_pattern;
-}
-
-#elif GTEST_USES_SIMPLE_RE
-
-// Returns true if and only if ch appears anywhere in str (excluding the
-// terminating '\0' character).
-bool IsInSet(char ch, const char* str) {
- return ch != '\0' && strchr(str, ch) != nullptr;
-}
-
-// Returns true if and only if ch belongs to the given classification.
-// Unlike similar functions in <ctype.h>, these aren't affected by the
-// current locale.
-bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
-bool IsAsciiPunct(char ch) {
- return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
-}
-bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
-bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
-bool IsAsciiWordChar(char ch) {
- return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
- ('0' <= ch && ch <= '9') || ch == '_';
-}
-
-// Returns true if and only if "\\c" is a supported escape sequence.
-bool IsValidEscape(char c) {
- return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
-}
-
-// Returns true if and only if the given atom (specified by escaped and
-// pattern) matches ch. The result is undefined if the atom is invalid.
-bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
- if (escaped) { // "\\p" where p is pattern_char.
- switch (pattern_char) {
- case 'd': return IsAsciiDigit(ch);
- case 'D': return !IsAsciiDigit(ch);
- case 'f': return ch == '\f';
- case 'n': return ch == '\n';
- case 'r': return ch == '\r';
- case 's': return IsAsciiWhiteSpace(ch);
- case 'S': return !IsAsciiWhiteSpace(ch);
- case 't': return ch == '\t';
- case 'v': return ch == '\v';
- case 'w': return IsAsciiWordChar(ch);
- case 'W': return !IsAsciiWordChar(ch);
- }
- return IsAsciiPunct(pattern_char) && pattern_char == ch;
- }
-
- return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
-}
-
-// Helper function used by ValidateRegex() to format error messages.
-static std::string FormatRegexSyntaxError(const char* regex, int index) {
- return (Message() << "Syntax error at index " << index
- << " in simple regular expression \"" << regex << "\": ").GetString();
-}
-
-// Generates non-fatal failures and returns false if regex is invalid;
-// otherwise returns true.
-bool ValidateRegex(const char* regex) {
- if (regex == nullptr) {
- ADD_FAILURE() << "NULL is not a valid simple regular expression.";
- return false;
- }
-
- bool is_valid = true;
-
- // True if and only if ?, *, or + can follow the previous atom.
- bool prev_repeatable = false;
- for (int i = 0; regex[i]; i++) {
- if (regex[i] == '\\') { // An escape sequence
- i++;
- if (regex[i] == '\0') {
- ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
- << "'\\' cannot appear at the end.";
- return false;
- }
-
- if (!IsValidEscape(regex[i])) {
- ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
- << "invalid escape sequence \"\\" << regex[i] << "\".";
- is_valid = false;
- }
- prev_repeatable = true;
- } else { // Not an escape sequence.
- const char ch = regex[i];
-
- if (ch == '^' && i > 0) {
- ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
- << "'^' can only appear at the beginning.";
- is_valid = false;
- } else if (ch == '$' && regex[i + 1] != '\0') {
- ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
- << "'$' can only appear at the end.";
- is_valid = false;
- } else if (IsInSet(ch, "()[]{}|")) {
- ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
- << "'" << ch << "' is unsupported.";
- is_valid = false;
- } else if (IsRepeat(ch) && !prev_repeatable) {
- ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
- << "'" << ch << "' can only follow a repeatable token.";
- is_valid = false;
- }
-
- prev_repeatable = !IsInSet(ch, "^$?*+");
- }
- }
-
- return is_valid;
-}
-
-// Matches a repeated regex atom followed by a valid simple regular
-// expression. The regex atom is defined as c if escaped is false,
-// or \c otherwise. repeat is the repetition meta character (?, *,
-// or +). The behavior is undefined if str contains too many
-// characters to be indexable by size_t, in which case the test will
-// probably time out anyway. We are fine with this limitation as
-// std::string has it too.
-bool MatchRepetitionAndRegexAtHead(
- bool escaped, char c, char repeat, const char* regex,
- const char* str) {
- const size_t min_count = (repeat == '+') ? 1 : 0;
- const size_t max_count = (repeat == '?') ? 1 :
- static_cast<size_t>(-1) - 1;
- // We cannot call numeric_limits::max() as it conflicts with the
- // max() macro on Windows.
-
- for (size_t i = 0; i <= max_count; ++i) {
- // We know that the atom matches each of the first i characters in str.
- if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
- // We have enough matches at the head, and the tail matches too.
- // Since we only care about *whether* the pattern matches str
- // (as opposed to *how* it matches), there is no need to find a
- // greedy match.
- return true;
- }
- if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
- return false;
- }
- return false;
-}
-
-// Returns true if and only if regex matches a prefix of str. regex must
-// be a valid simple regular expression and not start with "^", or the
-// result is undefined.
-bool MatchRegexAtHead(const char* regex, const char* str) {
- if (*regex == '\0') // An empty regex matches a prefix of anything.
- return true;
-
- // "$" only matches the end of a string. Note that regex being
- // valid guarantees that there's nothing after "$" in it.
- if (*regex == '$')
- return *str == '\0';
-
- // Is the first thing in regex an escape sequence?
- const bool escaped = *regex == '\\';
- if (escaped)
- ++regex;
- if (IsRepeat(regex[1])) {
- // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
- // here's an indirect recursion. It terminates as the regex gets
- // shorter in each recursion.
- return MatchRepetitionAndRegexAtHead(
- escaped, regex[0], regex[1], regex + 2, str);
- } else {
- // regex isn't empty, isn't "$", and doesn't start with a
- // repetition. We match the first atom of regex with the first
- // character of str and recurse.
- return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
- MatchRegexAtHead(regex + 1, str + 1);
- }
-}
-
-// Returns true if and only if regex matches any substring of str. regex must
-// be a valid simple regular expression, or the result is undefined.
-//
-// The algorithm is recursive, but the recursion depth doesn't exceed
-// the regex length, so we won't need to worry about running out of
-// stack space normally. In rare cases the time complexity can be
-// exponential with respect to the regex length + the string length,
-// but usually it's must faster (often close to linear).
-bool MatchRegexAnywhere(const char* regex, const char* str) {
- if (regex == nullptr || str == nullptr) return false;
-
- if (*regex == '^')
- return MatchRegexAtHead(regex + 1, str);
-
- // A successful match can be anywhere in str.
- do {
- if (MatchRegexAtHead(regex, str))
- return true;
- } while (*str++ != '\0');
- return false;
-}
-
-// Implements the RE class.
-
-RE::~RE() {
- free(const_cast<char*>(pattern_));
- free(const_cast<char*>(full_pattern_));
-}
-
-// Returns true if and only if regular expression re matches the entire str.
-bool RE::FullMatch(const char* str, const RE& re) {
- return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
-}
-
-// Returns true if and only if regular expression re matches a substring of
-// str (including str itself).
-bool RE::PartialMatch(const char* str, const RE& re) {
- return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
-}
-
-// Initializes an RE from its string representation.
-void RE::Init(const char* regex) {
- pattern_ = full_pattern_ = nullptr;
- if (regex != nullptr) {
- pattern_ = posix::StrDup(regex);
- }
-
- is_valid_ = ValidateRegex(regex);
- if (!is_valid_) {
- // No need to calculate the full pattern when the regex is invalid.
- return;
- }
-
- const size_t len = strlen(regex);
- // Reserves enough bytes to hold the regular expression used for a
- // full match: we need space to prepend a '^', append a '$', and
- // terminate the string with '\0'.
- char* buffer = static_cast<char*>(malloc(len + 3));
- full_pattern_ = buffer;
-
- if (*regex != '^')
- *buffer++ = '^'; // Makes sure full_pattern_ starts with '^'.
-
- // We don't use snprintf or strncpy, as they trigger a warning when
- // compiled with VC++ 8.0.
- memcpy(buffer, regex, len);
- buffer += len;
-
- if (len == 0 || regex[len - 1] != '$')
- *buffer++ = '$'; // Makes sure full_pattern_ ends with '$'.
-
- *buffer = '\0';
-}
-
-#endif // GTEST_USES_POSIX_RE
-
-const char kUnknownFile[] = "unknown file";
-
-// Formats a source file path and a line number as they would appear
-// in an error message from the compiler used to compile this code.
-GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
- const std::string file_name(file == nullptr ? kUnknownFile : file);
-
- if (line < 0) {
- return file_name + ":";
- }
-#ifdef _MSC_VER
- return file_name + "(" + StreamableToString(line) + "):";
-#else
- return file_name + ":" + StreamableToString(line) + ":";
-#endif // _MSC_VER
-}
-
-// Formats a file location for compiler-independent XML output.
-// Although this function is not platform dependent, we put it next to
-// FormatFileLocation in order to contrast the two functions.
-// Note that FormatCompilerIndependentFileLocation() does NOT append colon
-// to the file location it produces, unlike FormatFileLocation().
-GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
- const char* file, int line) {
- const std::string file_name(file == nullptr ? kUnknownFile : file);
-
- if (line < 0)
- return file_name;
- else
- return file_name + ":" + StreamableToString(line);
-}
-
-GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
- : severity_(severity) {
- const char* const marker =
- severity == GTEST_INFO ? "[ INFO ]" :
- severity == GTEST_WARNING ? "[WARNING]" :
- severity == GTEST_ERROR ? "[ ERROR ]" : "[ FATAL ]";
- GetStream() << ::std::endl << marker << " "
- << FormatFileLocation(file, line).c_str() << ": ";
-}
-
-// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
-GTestLog::~GTestLog() {
- GetStream() << ::std::endl;
- if (severity_ == GTEST_FATAL) {
- fflush(stderr);
- posix::Abort();
- }
-}
-
-// Disable Microsoft deprecation warnings for POSIX functions called from
-// this class (creat, dup, dup2, and close)
-GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
-
-#if GTEST_HAS_STREAM_REDIRECTION
-
-// Object that captures an output stream (stdout/stderr).
-class CapturedStream {
- public:
- // The ctor redirects the stream to a temporary file.
- explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
-# if GTEST_OS_WINDOWS
- char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
- char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
-
- ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
- const UINT success = ::GetTempFileNameA(temp_dir_path,
- "gtest_redir",
- 0, // Generate unique file name.
- temp_file_path);
- GTEST_CHECK_(success != 0)
- << "Unable to create a temporary file in " << temp_dir_path;
- const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
- GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
- << temp_file_path;
- filename_ = temp_file_path;
-# else
- // There's no guarantee that a test has write access to the current
- // directory, so we create the temporary file in the /tmp directory
- // instead. We use /tmp on most systems, and /sdcard on Android.
- // That's because Android doesn't have /tmp.
-# if GTEST_OS_LINUX_ANDROID
- // Note: Android applications are expected to call the framework's
- // Context.getExternalStorageDirectory() method through JNI to get
- // the location of the world-writable SD Card directory. However,
- // this requires a Context handle, which cannot be retrieved
- // globally from native code. Doing so also precludes running the
- // code as part of a regular standalone executable, which doesn't
- // run in a Dalvik process (e.g. when running it through 'adb shell').
- //
- // The location /data/local/tmp is directly accessible from native code.
- // '/sdcard' and other variants cannot be relied on, as they are not
- // guaranteed to be mounted, or may have a delay in mounting.
- char name_template[] = "/data/local/tmp/gtest_captured_stream.XXXXXX";
-# else
- char name_template[] = "/tmp/captured_stream.XXXXXX";
-# endif // GTEST_OS_LINUX_ANDROID
- const int captured_fd = mkstemp(name_template);
- if (captured_fd == -1) {
- GTEST_LOG_(WARNING)
- << "Failed to create tmp file " << name_template
- << " for test; does the test have access to the /tmp directory?";
- }
- filename_ = name_template;
-# endif // GTEST_OS_WINDOWS
- fflush(nullptr);
- dup2(captured_fd, fd_);
- close(captured_fd);
- }
-
- ~CapturedStream() {
- remove(filename_.c_str());
- }
-
- std::string GetCapturedString() {
- if (uncaptured_fd_ != -1) {
- // Restores the original stream.
- fflush(nullptr);
- dup2(uncaptured_fd_, fd_);
- close(uncaptured_fd_);
- uncaptured_fd_ = -1;
- }
-
- FILE* const file = posix::FOpen(filename_.c_str(), "r");
- if (file == nullptr) {
- GTEST_LOG_(FATAL) << "Failed to open tmp file " << filename_
- << " for capturing stream.";
- }
- const std::string content = ReadEntireFile(file);
- posix::FClose(file);
- return content;
- }
-
- private:
- const int fd_; // A stream to capture.
- int uncaptured_fd_;
- // Name of the temporary file holding the stderr output.
- ::std::string filename_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
-};
-
-GTEST_DISABLE_MSC_DEPRECATED_POP_()
-
-static CapturedStream* g_captured_stderr = nullptr;
-static CapturedStream* g_captured_stdout = nullptr;
-
-// Starts capturing an output stream (stdout/stderr).
-static void CaptureStream(int fd, const char* stream_name,
- CapturedStream** stream) {
- if (*stream != nullptr) {
- GTEST_LOG_(FATAL) << "Only one " << stream_name
- << " capturer can exist at a time.";
- }
- *stream = new CapturedStream(fd);
-}
-
-// Stops capturing the output stream and returns the captured string.
-static std::string GetCapturedStream(CapturedStream** captured_stream) {
- const std::string content = (*captured_stream)->GetCapturedString();
-
- delete *captured_stream;
- *captured_stream = nullptr;
-
- return content;
-}
-
-// Starts capturing stdout.
-void CaptureStdout() {
- CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
-}
-
-// Starts capturing stderr.
-void CaptureStderr() {
- CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
-}
-
-// Stops capturing stdout and returns the captured string.
-std::string GetCapturedStdout() {
- return GetCapturedStream(&g_captured_stdout);
-}
-
-// Stops capturing stderr and returns the captured string.
-std::string GetCapturedStderr() {
- return GetCapturedStream(&g_captured_stderr);
-}
-
-#endif // GTEST_HAS_STREAM_REDIRECTION
-
-
-
-
-
-size_t GetFileSize(FILE* file) {
- fseek(file, 0, SEEK_END);
- return static_cast<size_t>(ftell(file));
-}
-
-std::string ReadEntireFile(FILE* file) {
- const size_t file_size = GetFileSize(file);
- char* const buffer = new char[file_size];
-
- size_t bytes_last_read = 0; // # of bytes read in the last fread()
- size_t bytes_read = 0; // # of bytes read so far
-
- fseek(file, 0, SEEK_SET);
-
- // Keeps reading the file until we cannot read further or the
- // pre-determined file size is reached.
- do {
- bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
- bytes_read += bytes_last_read;
- } while (bytes_last_read > 0 && bytes_read < file_size);
-
- const std::string content(buffer, bytes_read);
- delete[] buffer;
-
- return content;
-}
-
-#if GTEST_HAS_DEATH_TEST
-static const std::vector<std::string>* g_injected_test_argvs =
- nullptr; // Owned.
-
-std::vector<std::string> GetInjectableArgvs() {
- if (g_injected_test_argvs != nullptr) {
- return *g_injected_test_argvs;
- }
- return GetArgvs();
-}
-
-void SetInjectableArgvs(const std::vector<std::string>* new_argvs) {
- if (g_injected_test_argvs != new_argvs) delete g_injected_test_argvs;
- g_injected_test_argvs = new_argvs;
-}
-
-void SetInjectableArgvs(const std::vector<std::string>& new_argvs) {
- SetInjectableArgvs(
- new std::vector<std::string>(new_argvs.begin(), new_argvs.end()));
-}
-
-void ClearInjectableArgvs() {
- delete g_injected_test_argvs;
- g_injected_test_argvs = nullptr;
-}
-#endif // GTEST_HAS_DEATH_TEST
-
-#if GTEST_OS_WINDOWS_MOBILE
-namespace posix {
-void Abort() {
- DebugBreak();
- TerminateProcess(GetCurrentProcess(), 1);
-}
-} // namespace posix
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-// Returns the name of the environment variable corresponding to the
-// given flag. For example, FlagToEnvVar("foo") will return
-// "GTEST_FOO" in the open-source version.
-static std::string FlagToEnvVar(const char* flag) {
- const std::string full_flag =
- (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
-
- Message env_var;
- for (size_t i = 0; i != full_flag.length(); i++) {
- env_var << ToUpper(full_flag.c_str()[i]);
- }
-
- return env_var.GetString();
-}
-
-// Parses 'str' for a 32-bit signed integer. If successful, writes
-// the result to *value and returns true; otherwise leaves *value
-// unchanged and returns false.
-bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
- // Parses the environment variable as a decimal integer.
- char* end = nullptr;
- const long long_value = strtol(str, &end, 10); // NOLINT
-
- // Has strtol() consumed all characters in the string?
- if (*end != '\0') {
- // No - an invalid character was encountered.
- Message msg;
- msg << "WARNING: " << src_text
- << " is expected to be a 32-bit integer, but actually"
- << " has value \"" << str << "\".\n";
- printf("%s", msg.GetString().c_str());
- fflush(stdout);
- return false;
- }
-
- // Is the parsed value in the range of an Int32?
- const Int32 result = static_cast<Int32>(long_value);
- if (long_value == LONG_MAX || long_value == LONG_MIN ||
- // The parsed value overflows as a long. (strtol() returns
- // LONG_MAX or LONG_MIN when the input overflows.)
- result != long_value
- // The parsed value overflows as an Int32.
- ) {
- Message msg;
- msg << "WARNING: " << src_text
- << " is expected to be a 32-bit integer, but actually"
- << " has value " << str << ", which overflows.\n";
- printf("%s", msg.GetString().c_str());
- fflush(stdout);
- return false;
- }
-
- *value = result;
- return true;
-}
-
-// Reads and returns the Boolean environment variable corresponding to
-// the given flag; if it's not set, returns default_value.
-//
-// The value is considered true if and only if it's not "0".
-bool BoolFromGTestEnv(const char* flag, bool default_value) {
-#if defined(GTEST_GET_BOOL_FROM_ENV_)
- return GTEST_GET_BOOL_FROM_ENV_(flag, default_value);
-#else
- const std::string env_var = FlagToEnvVar(flag);
- const char* const string_value = posix::GetEnv(env_var.c_str());
- return string_value == nullptr ? default_value
- : strcmp(string_value, "0") != 0;
-#endif // defined(GTEST_GET_BOOL_FROM_ENV_)
-}
-
-// Reads and returns a 32-bit integer stored in the environment
-// variable corresponding to the given flag; if it isn't set or
-// doesn't represent a valid 32-bit integer, returns default_value.
-Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
-#if defined(GTEST_GET_INT32_FROM_ENV_)
- return GTEST_GET_INT32_FROM_ENV_(flag, default_value);
-#else
- const std::string env_var = FlagToEnvVar(flag);
- const char* const string_value = posix::GetEnv(env_var.c_str());
- if (string_value == nullptr) {
- // The environment variable is not set.
- return default_value;
- }
-
- Int32 result = default_value;
- if (!ParseInt32(Message() << "Environment variable " << env_var,
- string_value, &result)) {
- printf("The default value %s is used.\n",
- (Message() << default_value).GetString().c_str());
- fflush(stdout);
- return default_value;
- }
-
- return result;
-#endif // defined(GTEST_GET_INT32_FROM_ENV_)
-}
-
-// As a special case for the 'output' flag, if GTEST_OUTPUT is not
-// set, we look for XML_OUTPUT_FILE, which is set by the Bazel build
-// system. The value of XML_OUTPUT_FILE is a filename without the
-// "xml:" prefix of GTEST_OUTPUT.
-// Note that this is meant to be called at the call site so it does
-// not check that the flag is 'output'
-// In essence this checks an env variable called XML_OUTPUT_FILE
-// and if it is set we prepend "xml:" to its value, if it not set we return ""
-std::string OutputFlagAlsoCheckEnvVar(){
- std::string default_value_for_output_flag = "";
- const char* xml_output_file_env = posix::GetEnv("XML_OUTPUT_FILE");
- if (nullptr != xml_output_file_env) {
- default_value_for_output_flag = std::string("xml:") + xml_output_file_env;
- }
- return default_value_for_output_flag;
-}
-
-// Reads and returns the string environment variable corresponding to
-// the given flag; if it's not set, returns default_value.
-const char* StringFromGTestEnv(const char* flag, const char* default_value) {
-#if defined(GTEST_GET_STRING_FROM_ENV_)
- return GTEST_GET_STRING_FROM_ENV_(flag, default_value);
-#else
- const std::string env_var = FlagToEnvVar(flag);
- const char* const value = posix::GetEnv(env_var.c_str());
- return value == nullptr ? default_value : value;
-#endif // defined(GTEST_GET_STRING_FROM_ENV_)
-}
-
-} // namespace internal
-} // namespace testing
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Google Test - The Google C++ Testing and Mocking Framework
-//
-// This file implements a universal value printer that can print a
-// value of any type T:
-//
-// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
-//
-// It uses the << operator when possible, and prints the bytes in the
-// object otherwise. A user can override its behavior for a class
-// type Foo by defining either operator<<(::std::ostream&, const Foo&)
-// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
-// defines Foo.
-
-#include "gtest/gtest-printers.h"
-#include <stdio.h>
-#include <cctype>
-#include <cwchar>
-#include <ostream> // NOLINT
-#include <string>
-#include "gtest/internal/gtest-port.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-
-namespace {
-
-using ::std::ostream;
-
-// Prints a segment of bytes in the given object.
-GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
-GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
-void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
- size_t count, ostream* os) {
- char text[5] = "";
- for (size_t i = 0; i != count; i++) {
- const size_t j = start + i;
- if (i != 0) {
- // Organizes the bytes into groups of 2 for easy parsing by
- // human.
- if ((j % 2) == 0)
- *os << ' ';
- else
- *os << '-';
- }
- GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
- *os << text;
- }
-}
-
-// Prints the bytes in the given value to the given ostream.
-void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
- ostream* os) {
- // Tells the user how big the object is.
- *os << count << "-byte object <";
-
- const size_t kThreshold = 132;
- const size_t kChunkSize = 64;
- // If the object size is bigger than kThreshold, we'll have to omit
- // some details by printing only the first and the last kChunkSize
- // bytes.
- if (count < kThreshold) {
- PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
- } else {
- PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
- *os << " ... ";
- // Rounds up to 2-byte boundary.
- const size_t resume_pos = (count - kChunkSize + 1)/2*2;
- PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
- }
- *os << ">";
-}
-
-} // namespace
-
-namespace internal2 {
-
-// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
-// given object. The delegation simplifies the implementation, which
-// uses the << operator and thus is easier done outside of the
-// ::testing::internal namespace, which contains a << operator that
-// sometimes conflicts with the one in STL.
-void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
- ostream* os) {
- PrintBytesInObjectToImpl(obj_bytes, count, os);
-}
-
-} // namespace internal2
-
-namespace internal {
-
-// Depending on the value of a char (or wchar_t), we print it in one
-// of three formats:
-// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
-// - as a hexadecimal escape sequence (e.g. '\x7F'), or
-// - as a special escape sequence (e.g. '\r', '\n').
-enum CharFormat {
- kAsIs,
- kHexEscape,
- kSpecialEscape
-};
-
-// Returns true if c is a printable ASCII character. We test the
-// value of c directly instead of calling isprint(), which is buggy on
-// Windows Mobile.
-inline bool IsPrintableAscii(wchar_t c) {
- return 0x20 <= c && c <= 0x7E;
-}
-
-// Prints a wide or narrow char c as a character literal without the
-// quotes, escaping it when necessary; returns how c was formatted.
-// The template argument UnsignedChar is the unsigned version of Char,
-// which is the type of c.
-template <typename UnsignedChar, typename Char>
-static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
- wchar_t w_c = static_cast<wchar_t>(c);
- switch (w_c) {
- case L'\0':
- *os << "\\0";
- break;
- case L'\'':
- *os << "\\'";
- break;
- case L'\\':
- *os << "\\\\";
- break;
- case L'\a':
- *os << "\\a";
- break;
- case L'\b':
- *os << "\\b";
- break;
- case L'\f':
- *os << "\\f";
- break;
- case L'\n':
- *os << "\\n";
- break;
- case L'\r':
- *os << "\\r";
- break;
- case L'\t':
- *os << "\\t";
- break;
- case L'\v':
- *os << "\\v";
- break;
- default:
- if (IsPrintableAscii(w_c)) {
- *os << static_cast<char>(c);
- return kAsIs;
- } else {
- ostream::fmtflags flags = os->flags();
- *os << "\\x" << std::hex << std::uppercase
- << static_cast<int>(static_cast<UnsignedChar>(c));
- os->flags(flags);
- return kHexEscape;
- }
- }
- return kSpecialEscape;
-}
-
-// Prints a wchar_t c as if it's part of a string literal, escaping it when
-// necessary; returns how c was formatted.
-static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
- switch (c) {
- case L'\'':
- *os << "'";
- return kAsIs;
- case L'"':
- *os << "\\\"";
- return kSpecialEscape;
- default:
- return PrintAsCharLiteralTo<wchar_t>(c, os);
- }
-}
-
-// Prints a char c as if it's part of a string literal, escaping it when
-// necessary; returns how c was formatted.
-static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
- return PrintAsStringLiteralTo(
- static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
-}
-
-// Prints a wide or narrow character c and its code. '\0' is printed
-// as "'\\0'", other unprintable characters are also properly escaped
-// using the standard C++ escape sequence. The template argument
-// UnsignedChar is the unsigned version of Char, which is the type of c.
-template <typename UnsignedChar, typename Char>
-void PrintCharAndCodeTo(Char c, ostream* os) {
- // First, print c as a literal in the most readable form we can find.
- *os << ((sizeof(c) > 1) ? "L'" : "'");
- const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
- *os << "'";
-
- // To aid user debugging, we also print c's code in decimal, unless
- // it's 0 (in which case c was printed as '\\0', making the code
- // obvious).
- if (c == 0)
- return;
- *os << " (" << static_cast<int>(c);
-
- // For more convenience, we print c's code again in hexadecimal,
- // unless c was already printed in the form '\x##' or the code is in
- // [1, 9].
- if (format == kHexEscape || (1 <= c && c <= 9)) {
- // Do nothing.
- } else {
- *os << ", 0x" << String::FormatHexInt(static_cast<int>(c));
- }
- *os << ")";
-}
-
-void PrintTo(unsigned char c, ::std::ostream* os) {
- PrintCharAndCodeTo<unsigned char>(c, os);
-}
-void PrintTo(signed char c, ::std::ostream* os) {
- PrintCharAndCodeTo<unsigned char>(c, os);
-}
-
-// Prints a wchar_t as a symbol if it is printable or as its internal
-// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
-void PrintTo(wchar_t wc, ostream* os) {
- PrintCharAndCodeTo<wchar_t>(wc, os);
-}
-
-// Prints the given array of characters to the ostream. CharType must be either
-// char or wchar_t.
-// The array starts at begin, the length is len, it may include '\0' characters
-// and may not be NUL-terminated.
-template <typename CharType>
-GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
-GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
-static CharFormat PrintCharsAsStringTo(
- const CharType* begin, size_t len, ostream* os) {
- const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
- *os << kQuoteBegin;
- bool is_previous_hex = false;
- CharFormat print_format = kAsIs;
- for (size_t index = 0; index < len; ++index) {
- const CharType cur = begin[index];
- if (is_previous_hex && IsXDigit(cur)) {
- // Previous character is of '\x..' form and this character can be
- // interpreted as another hexadecimal digit in its number. Break string to
- // disambiguate.
- *os << "\" " << kQuoteBegin;
- }
- is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
- // Remember if any characters required hex escaping.
- if (is_previous_hex) {
- print_format = kHexEscape;
- }
- }
- *os << "\"";
- return print_format;
-}
-
-// Prints a (const) char/wchar_t array of 'len' elements, starting at address
-// 'begin'. CharType must be either char or wchar_t.
-template <typename CharType>
-GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
-GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_HWADDRESS_
-GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
-static void UniversalPrintCharArray(
- const CharType* begin, size_t len, ostream* os) {
- // The code
- // const char kFoo[] = "foo";
- // generates an array of 4, not 3, elements, with the last one being '\0'.
- //
- // Therefore when printing a char array, we don't print the last element if
- // it's '\0', such that the output matches the string literal as it's
- // written in the source code.
- if (len > 0 && begin[len - 1] == '\0') {
- PrintCharsAsStringTo(begin, len - 1, os);
- return;
- }
-
- // If, however, the last element in the array is not '\0', e.g.
- // const char kFoo[] = { 'f', 'o', 'o' };
- // we must print the entire array. We also print a message to indicate
- // that the array is not NUL-terminated.
- PrintCharsAsStringTo(begin, len, os);
- *os << " (no terminating NUL)";
-}
-
-// Prints a (const) char array of 'len' elements, starting at address 'begin'.
-void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
- UniversalPrintCharArray(begin, len, os);
-}
-
-// Prints a (const) wchar_t array of 'len' elements, starting at address
-// 'begin'.
-void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
- UniversalPrintCharArray(begin, len, os);
-}
-
-// Prints the given C string to the ostream.
-void PrintTo(const char* s, ostream* os) {
- if (s == nullptr) {
- *os << "NULL";
- } else {
- *os << ImplicitCast_<const void*>(s) << " pointing to ";
- PrintCharsAsStringTo(s, strlen(s), os);
- }
-}
-
-// MSVC compiler can be configured to define whar_t as a typedef
-// of unsigned short. Defining an overload for const wchar_t* in that case
-// would cause pointers to unsigned shorts be printed as wide strings,
-// possibly accessing more memory than intended and causing invalid
-// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
-// wchar_t is implemented as a native type.
-#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-// Prints the given wide C string to the ostream.
-void PrintTo(const wchar_t* s, ostream* os) {
- if (s == nullptr) {
- *os << "NULL";
- } else {
- *os << ImplicitCast_<const void*>(s) << " pointing to ";
- PrintCharsAsStringTo(s, wcslen(s), os);
- }
-}
-#endif // wchar_t is native
-
-namespace {
-
-bool ContainsUnprintableControlCodes(const char* str, size_t length) {
- const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
-
- for (size_t i = 0; i < length; i++) {
- unsigned char ch = *s++;
- if (std::iscntrl(ch)) {
- switch (ch) {
- case '\t':
- case '\n':
- case '\r':
- break;
- default:
- return true;
- }
- }
- }
- return false;
-}
-
-bool IsUTF8TrailByte(unsigned char t) { return 0x80 <= t && t<= 0xbf; }
-
-bool IsValidUTF8(const char* str, size_t length) {
- const unsigned char *s = reinterpret_cast<const unsigned char *>(str);
-
- for (size_t i = 0; i < length;) {
- unsigned char lead = s[i++];
-
- if (lead <= 0x7f) {
- continue; // single-byte character (ASCII) 0..7F
- }
- if (lead < 0xc2) {
- return false; // trail byte or non-shortest form
- } else if (lead <= 0xdf && (i + 1) <= length && IsUTF8TrailByte(s[i])) {
- ++i; // 2-byte character
- } else if (0xe0 <= lead && lead <= 0xef && (i + 2) <= length &&
- IsUTF8TrailByte(s[i]) &&
- IsUTF8TrailByte(s[i + 1]) &&
- // check for non-shortest form and surrogate
- (lead != 0xe0 || s[i] >= 0xa0) &&
- (lead != 0xed || s[i] < 0xa0)) {
- i += 2; // 3-byte character
- } else if (0xf0 <= lead && lead <= 0xf4 && (i + 3) <= length &&
- IsUTF8TrailByte(s[i]) &&
- IsUTF8TrailByte(s[i + 1]) &&
- IsUTF8TrailByte(s[i + 2]) &&
- // check for non-shortest form
- (lead != 0xf0 || s[i] >= 0x90) &&
- (lead != 0xf4 || s[i] < 0x90)) {
- i += 3; // 4-byte character
- } else {
- return false;
- }
- }
- return true;
-}
-
-void ConditionalPrintAsText(const char* str, size_t length, ostream* os) {
- if (!ContainsUnprintableControlCodes(str, length) &&
- IsValidUTF8(str, length)) {
- *os << "\n As Text: \"" << str << "\"";
- }
-}
-
-} // anonymous namespace
-
-void PrintStringTo(const ::std::string& s, ostream* os) {
- if (PrintCharsAsStringTo(s.data(), s.size(), os) == kHexEscape) {
- if (GTEST_FLAG(print_utf8)) {
- ConditionalPrintAsText(s.data(), s.size(), os);
- }
- }
-}
-
-#if GTEST_HAS_STD_WSTRING
-void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
- PrintCharsAsStringTo(s.data(), s.size(), os);
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-} // namespace internal
-
-} // namespace testing
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-
-#include "gtest/gtest-test-part.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-
-using internal::GetUnitTestImpl;
-
-// Gets the summary of the failure message by omitting the stack trace
-// in it.
-std::string TestPartResult::ExtractSummary(const char* message) {
- const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
- return stack_trace == nullptr ? message : std::string(message, stack_trace);
-}
-
-// Prints a TestPartResult object.
-std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
- return os << result.file_name() << ":" << result.line_number() << ": "
- << (result.type() == TestPartResult::kSuccess
- ? "Success"
- : result.type() == TestPartResult::kSkip
- ? "Skipped"
- : result.type() == TestPartResult::kFatalFailure
- ? "Fatal failure"
- : "Non-fatal failure")
- << ":\n"
- << result.message() << std::endl;
-}
-
-// Appends a TestPartResult to the array.
-void TestPartResultArray::Append(const TestPartResult& result) {
- array_.push_back(result);
-}
-
-// Returns the TestPartResult at the given index (0-based).
-const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
- if (index < 0 || index >= size()) {
- printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
- internal::posix::Abort();
- }
-
- return array_[static_cast<size_t>(index)];
-}
-
-// Returns the number of TestPartResult objects in the array.
-int TestPartResultArray::size() const {
- return static_cast<int>(array_.size());
-}
-
-namespace internal {
-
-HasNewFatalFailureHelper::HasNewFatalFailureHelper()
- : has_new_fatal_failure_(false),
- original_reporter_(GetUnitTestImpl()->
- GetTestPartResultReporterForCurrentThread()) {
- GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
-}
-
-HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
- GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
- original_reporter_);
-}
-
-void HasNewFatalFailureHelper::ReportTestPartResult(
- const TestPartResult& result) {
- if (result.fatally_failed())
- has_new_fatal_failure_ = true;
- original_reporter_->ReportTestPartResult(result);
-}
-
-} // namespace internal
-
-} // namespace testing
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "gtest/gtest-typed-test.h"
-
-#include "gtest/gtest.h"
-
-namespace testing {
-namespace internal {
-
-#if GTEST_HAS_TYPED_TEST_P
-
-// Skips to the first non-space char in str. Returns an empty string if str
-// contains only whitespace characters.
-static const char* SkipSpaces(const char* str) {
- while (IsSpace(*str))
- str++;
- return str;
-}
-
-static std::vector<std::string> SplitIntoTestNames(const char* src) {
- std::vector<std::string> name_vec;
- src = SkipSpaces(src);
- for (; src != nullptr; src = SkipComma(src)) {
- name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
- }
- return name_vec;
-}
-
-// Verifies that registered_tests match the test names in
-// registered_tests_; returns registered_tests if successful, or
-// aborts the program otherwise.
-const char* TypedTestSuitePState::VerifyRegisteredTestNames(
- const char* file, int line, const char* registered_tests) {
- typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
- registered_ = true;
-
- std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
-
- Message errors;
-
- std::set<std::string> tests;
- for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
- name_it != name_vec.end(); ++name_it) {
- const std::string& name = *name_it;
- if (tests.count(name) != 0) {
- errors << "Test " << name << " is listed more than once.\n";
- continue;
- }
-
- bool found = false;
- for (RegisteredTestIter it = registered_tests_.begin();
- it != registered_tests_.end();
- ++it) {
- if (name == it->first) {
- found = true;
- break;
- }
- }
-
- if (found) {
- tests.insert(name);
- } else {
- errors << "No test named " << name
- << " can be found in this test suite.\n";
- }
- }
-
- for (RegisteredTestIter it = registered_tests_.begin();
- it != registered_tests_.end();
- ++it) {
- if (tests.count(it->first) == 0) {
- errors << "You forgot to list test " << it->first << ".\n";
- }
- }
-
- const std::string& errors_str = errors.GetString();
- if (errors_str != "") {
- fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
- errors_str.c_str());
- fflush(stderr);
- posix::Abort();
- }
-
- return registered_tests;
-}
-
-#endif // GTEST_HAS_TYPED_TEST_P
-
-} // namespace internal
-} // namespace testing
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-
-#include "gtest/gtest.h"
-#include "gtest/internal/custom/gtest.h"
-#include "gtest/gtest-spi.h"
-
-#include <ctype.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include <algorithm>
-#include <iomanip>
-#include <limits>
-#include <list>
-#include <map>
-#include <ostream> // NOLINT
-#include <sstream>
-#include <vector>
-
-#if GTEST_OS_LINUX
-
-# define GTEST_HAS_GETTIMEOFDAY_ 1
-
-# include <fcntl.h> // NOLINT
-# include <limits.h> // NOLINT
-# include <sched.h> // NOLINT
-// Declares vsnprintf(). This header is not available on Windows.
-# include <strings.h> // NOLINT
-# include <sys/mman.h> // NOLINT
-# include <sys/time.h> // NOLINT
-# include <unistd.h> // NOLINT
-# include <string>
-
-#elif GTEST_OS_ZOS
-# define GTEST_HAS_GETTIMEOFDAY_ 1
-# include <sys/time.h> // NOLINT
-
-// On z/OS we additionally need strings.h for strcasecmp.
-# include <strings.h> // NOLINT
-
-#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
-
-# include <windows.h> // NOLINT
-# undef min
-
-#elif GTEST_OS_WINDOWS // We are on Windows proper.
-
-# include <windows.h> // NOLINT
-# undef min
-
-# include <crtdbg.h> // NOLINT
-# include <debugapi.h> // NOLINT
-# include <io.h> // NOLINT
-# include <sys/timeb.h> // NOLINT
-# include <sys/types.h> // NOLINT
-# include <sys/stat.h> // NOLINT
-
-# if GTEST_OS_WINDOWS_MINGW
-// MinGW has gettimeofday() but not _ftime64().
-# define GTEST_HAS_GETTIMEOFDAY_ 1
-# include <sys/time.h> // NOLINT
-# endif // GTEST_OS_WINDOWS_MINGW
-
-#else
-
-// Assume other platforms have gettimeofday().
-# define GTEST_HAS_GETTIMEOFDAY_ 1
-
-// cpplint thinks that the header is already included, so we want to
-// silence it.
-# include <sys/time.h> // NOLINT
-# include <unistd.h> // NOLINT
-
-#endif // GTEST_OS_LINUX
-
-#if GTEST_HAS_EXCEPTIONS
-# include <stdexcept>
-#endif
-
-#if GTEST_CAN_STREAM_RESULTS_
-# include <arpa/inet.h> // NOLINT
-# include <netdb.h> // NOLINT
-# include <sys/socket.h> // NOLINT
-# include <sys/types.h> // NOLINT
-#endif
-
-#include "src/gtest-internal-inl.h"
-
-#if GTEST_OS_WINDOWS
-# define vsnprintf _vsnprintf
-#endif // GTEST_OS_WINDOWS
-
-#if GTEST_OS_MAC
-#ifndef GTEST_OS_IOS
-#include <crt_externs.h>
-#endif
-#endif
-
-#if GTEST_HAS_ABSL
-#include "absl/debugging/failure_signal_handler.h"
-#include "absl/debugging/stacktrace.h"
-#include "absl/debugging/symbolize.h"
-#include "absl/strings/str_cat.h"
-#endif // GTEST_HAS_ABSL
-
-namespace testing {
-
-using internal::CountIf;
-using internal::ForEach;
-using internal::GetElementOr;
-using internal::Shuffle;
-
-// Constants.
-
-// A test whose test suite name or test name matches this filter is
-// disabled and not run.
-static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
-
-// A test suite whose name matches this filter is considered a death
-// test suite and will be run before test suites whose name doesn't
-// match this filter.
-static const char kDeathTestSuiteFilter[] = "*DeathTest:*DeathTest/*";
-
-// A test filter that matches everything.
-static const char kUniversalFilter[] = "*";
-
-// The default output format.
-static const char kDefaultOutputFormat[] = "xml";
-// The default output file.
-static const char kDefaultOutputFile[] = "test_detail";
-
-// The environment variable name for the test shard index.
-static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
-// The environment variable name for the total number of test shards.
-static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
-// The environment variable name for the test shard status file.
-static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
-
-namespace internal {
-
-// The text used in failure messages to indicate the start of the
-// stack trace.
-const char kStackTraceMarker[] = "\nStack trace:\n";
-
-// g_help_flag is true if and only if the --help flag or an equivalent form
-// is specified on the command line.
-bool g_help_flag = false;
-
-// Utilty function to Open File for Writing
-static FILE* OpenFileForWriting(const std::string& output_file) {
- FILE* fileout = nullptr;
- FilePath output_file_path(output_file);
- FilePath output_dir(output_file_path.RemoveFileName());
-
- if (output_dir.CreateDirectoriesRecursively()) {
- fileout = posix::FOpen(output_file.c_str(), "w");
- }
- if (fileout == nullptr) {
- GTEST_LOG_(FATAL) << "Unable to open file \"" << output_file << "\"";
- }
- return fileout;
-}
-
-} // namespace internal
-
-// Bazel passes in the argument to '--test_filter' via the TESTBRIDGE_TEST_ONLY
-// environment variable.
-static const char* GetDefaultFilter() {
- const char* const testbridge_test_only =
- internal::posix::GetEnv("TESTBRIDGE_TEST_ONLY");
- if (testbridge_test_only != nullptr) {
- return testbridge_test_only;
- }
- return kUniversalFilter;
-}
-
-GTEST_DEFINE_bool_(
- also_run_disabled_tests,
- internal::BoolFromGTestEnv("also_run_disabled_tests", false),
- "Run disabled tests too, in addition to the tests normally being run.");
-
-GTEST_DEFINE_bool_(
- break_on_failure, internal::BoolFromGTestEnv("break_on_failure", false),
- "True if and only if a failed assertion should be a debugger "
- "break-point.");
-
-GTEST_DEFINE_bool_(catch_exceptions,
- internal::BoolFromGTestEnv("catch_exceptions", true),
- "True if and only if " GTEST_NAME_
- " should catch exceptions and treat them as test failures.");
-
-GTEST_DEFINE_string_(
- color,
- internal::StringFromGTestEnv("color", "auto"),
- "Whether to use colors in the output. Valid values: yes, no, "
- "and auto. 'auto' means to use colors if the output is "
- "being sent to a terminal and the TERM environment variable "
- "is set to a terminal type that supports colors.");
-
-GTEST_DEFINE_string_(
- filter,
- internal::StringFromGTestEnv("filter", GetDefaultFilter()),
- "A colon-separated list of glob (not regex) patterns "
- "for filtering the tests to run, optionally followed by a "
- "'-' and a : separated list of negative patterns (tests to "
- "exclude). A test is run if it matches one of the positive "
- "patterns and does not match any of the negative patterns.");
-
-GTEST_DEFINE_bool_(
- install_failure_signal_handler,
- internal::BoolFromGTestEnv("install_failure_signal_handler", false),
- "If true and supported on the current platform, " GTEST_NAME_ " should "
- "install a signal handler that dumps debugging information when fatal "
- "signals are raised.");
-
-GTEST_DEFINE_bool_(list_tests, false,
- "List all tests without running them.");
-
-// The net priority order after flag processing is thus:
-// --gtest_output command line flag
-// GTEST_OUTPUT environment variable
-// XML_OUTPUT_FILE environment variable
-// ''
-GTEST_DEFINE_string_(
- output,
- internal::StringFromGTestEnv("output",
- internal::OutputFlagAlsoCheckEnvVar().c_str()),
- "A format (defaults to \"xml\" but can be specified to be \"json\"), "
- "optionally followed by a colon and an output file name or directory. "
- "A directory is indicated by a trailing pathname separator. "
- "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
- "If a directory is specified, output files will be created "
- "within that directory, with file-names based on the test "
- "executable's name and, if necessary, made unique by adding "
- "digits.");
-
-GTEST_DEFINE_bool_(print_time, internal::BoolFromGTestEnv("print_time", true),
- "True if and only if " GTEST_NAME_
- " should display elapsed time in text output.");
-
-GTEST_DEFINE_bool_(print_utf8, internal::BoolFromGTestEnv("print_utf8", true),
- "True if and only if " GTEST_NAME_
- " prints UTF8 characters as text.");
-
-GTEST_DEFINE_int32_(
- random_seed,
- internal::Int32FromGTestEnv("random_seed", 0),
- "Random number seed to use when shuffling test orders. Must be in range "
- "[1, 99999], or 0 to use a seed based on the current time.");
-
-GTEST_DEFINE_int32_(
- repeat,
- internal::Int32FromGTestEnv("repeat", 1),
- "How many times to repeat each test. Specify a negative number "
- "for repeating forever. Useful for shaking out flaky tests.");
-
-GTEST_DEFINE_bool_(show_internal_stack_frames, false,
- "True if and only if " GTEST_NAME_
- " should include internal stack frames when "
- "printing test failure stack traces.");
-
-GTEST_DEFINE_bool_(shuffle, internal::BoolFromGTestEnv("shuffle", false),
- "True if and only if " GTEST_NAME_
- " should randomize tests' order on every run.");
-
-GTEST_DEFINE_int32_(
- stack_trace_depth,
- internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
- "The maximum number of stack frames to print when an "
- "assertion fails. The valid range is 0 through 100, inclusive.");
-
-GTEST_DEFINE_string_(
- stream_result_to,
- internal::StringFromGTestEnv("stream_result_to", ""),
- "This flag specifies the host name and the port number on which to stream "
- "test results. Example: \"localhost:555\". The flag is effective only on "
- "Linux.");
-
-GTEST_DEFINE_bool_(
- throw_on_failure,
- internal::BoolFromGTestEnv("throw_on_failure", false),
- "When this flag is specified, a failed assertion will throw an exception "
- "if exceptions are enabled or exit the program with a non-zero code "
- "otherwise. For use with an external test framework.");
-
-#if GTEST_USE_OWN_FLAGFILE_FLAG_
-GTEST_DEFINE_string_(
- flagfile,
- internal::StringFromGTestEnv("flagfile", ""),
- "This flag specifies the flagfile to read command-line flags from.");
-#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
-
-namespace internal {
-
-// Generates a random number from [0, range), using a Linear
-// Congruential Generator (LCG). Crashes if 'range' is 0 or greater
-// than kMaxRange.
-UInt32 Random::Generate(UInt32 range) {
- // These constants are the same as are used in glibc's rand(3).
- // Use wider types than necessary to prevent unsigned overflow diagnostics.
- state_ = static_cast<UInt32>(1103515245ULL*state_ + 12345U) % kMaxRange;
-
- GTEST_CHECK_(range > 0)
- << "Cannot generate a number in the range [0, 0).";
- GTEST_CHECK_(range <= kMaxRange)
- << "Generation of a number in [0, " << range << ") was requested, "
- << "but this can only generate numbers in [0, " << kMaxRange << ").";
-
- // Converting via modulus introduces a bit of downward bias, but
- // it's simple, and a linear congruential generator isn't too good
- // to begin with.
- return state_ % range;
-}
-
-// GTestIsInitialized() returns true if and only if the user has initialized
-// Google Test. Useful for catching the user mistake of not initializing
-// Google Test before calling RUN_ALL_TESTS().
-static bool GTestIsInitialized() { return GetArgvs().size() > 0; }
-
-// Iterates over a vector of TestSuites, keeping a running sum of the
-// results of calling a given int-returning method on each.
-// Returns the sum.
-static int SumOverTestSuiteList(const std::vector<TestSuite*>& case_list,
- int (TestSuite::*method)() const) {
- int sum = 0;
- for (size_t i = 0; i < case_list.size(); i++) {
- sum += (case_list[i]->*method)();
- }
- return sum;
-}
-
-// Returns true if and only if the test suite passed.
-static bool TestSuitePassed(const TestSuite* test_suite) {
- return test_suite->should_run() && test_suite->Passed();
-}
-
-// Returns true if and only if the test suite failed.
-static bool TestSuiteFailed(const TestSuite* test_suite) {
- return test_suite->should_run() && test_suite->Failed();
-}
-
-// Returns true if and only if test_suite contains at least one test that
-// should run.
-static bool ShouldRunTestSuite(const TestSuite* test_suite) {
- return test_suite->should_run();
-}
-
-// AssertHelper constructor.
-AssertHelper::AssertHelper(TestPartResult::Type type,
- const char* file,
- int line,
- const char* message)
- : data_(new AssertHelperData(type, file, line, message)) {
-}
-
-AssertHelper::~AssertHelper() {
- delete data_;
-}
-
-// Message assignment, for assertion streaming support.
-void AssertHelper::operator=(const Message& message) const {
- UnitTest::GetInstance()->
- AddTestPartResult(data_->type, data_->file, data_->line,
- AppendUserMessage(data_->message, message),
- UnitTest::GetInstance()->impl()
- ->CurrentOsStackTraceExceptTop(1)
- // Skips the stack frame for this function itself.
- ); // NOLINT
-}
-
-// A copy of all command line arguments. Set by InitGoogleTest().
-static ::std::vector<std::string> g_argvs;
-
-::std::vector<std::string> GetArgvs() {
-#if defined(GTEST_CUSTOM_GET_ARGVS_)
- // GTEST_CUSTOM_GET_ARGVS_() may return a container of std::string or
- // ::string. This code converts it to the appropriate type.
- const auto& custom = GTEST_CUSTOM_GET_ARGVS_();
- return ::std::vector<std::string>(custom.begin(), custom.end());
-#else // defined(GTEST_CUSTOM_GET_ARGVS_)
- return g_argvs;
-#endif // defined(GTEST_CUSTOM_GET_ARGVS_)
-}
-
-// Returns the current application's name, removing directory path if that
-// is present.
-FilePath GetCurrentExecutableName() {
- FilePath result;
-
-#if GTEST_OS_WINDOWS || GTEST_OS_OS2
- result.Set(FilePath(GetArgvs()[0]).RemoveExtension("exe"));
-#else
- result.Set(FilePath(GetArgvs()[0]));
-#endif // GTEST_OS_WINDOWS
-
- return result.RemoveDirectoryName();
-}
-
-// Functions for processing the gtest_output flag.
-
-// Returns the output format, or "" for normal printed output.
-std::string UnitTestOptions::GetOutputFormat() {
- const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
- const char* const colon = strchr(gtest_output_flag, ':');
- return (colon == nullptr)
- ? std::string(gtest_output_flag)
- : std::string(gtest_output_flag,
- static_cast<size_t>(colon - gtest_output_flag));
-}
-
-// Returns the name of the requested output file, or the default if none
-// was explicitly specified.
-std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
- const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
-
- std::string format = GetOutputFormat();
- if (format.empty())
- format = std::string(kDefaultOutputFormat);
-
- const char* const colon = strchr(gtest_output_flag, ':');
- if (colon == nullptr)
- return internal::FilePath::MakeFileName(
- internal::FilePath(
- UnitTest::GetInstance()->original_working_dir()),
- internal::FilePath(kDefaultOutputFile), 0,
- format.c_str()).string();
-
- internal::FilePath output_name(colon + 1);
- if (!output_name.IsAbsolutePath())
- output_name = internal::FilePath::ConcatPaths(
- internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
- internal::FilePath(colon + 1));
-
- if (!output_name.IsDirectory())
- return output_name.string();
-
- internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
- output_name, internal::GetCurrentExecutableName(),
- GetOutputFormat().c_str()));
- return result.string();
-}
-
-// Returns true if and only if the wildcard pattern matches the string.
-// The first ':' or '\0' character in pattern marks the end of it.
-//
-// This recursive algorithm isn't very efficient, but is clear and
-// works well enough for matching test names, which are short.
-bool UnitTestOptions::PatternMatchesString(const char *pattern,
- const char *str) {
- switch (*pattern) {
- case '\0':
- case ':': // Either ':' or '\0' marks the end of the pattern.
- return *str == '\0';
- case '?': // Matches any single character.
- return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
- case '*': // Matches any string (possibly empty) of characters.
- return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
- PatternMatchesString(pattern + 1, str);
- default: // Non-special character. Matches itself.
- return *pattern == *str &&
- PatternMatchesString(pattern + 1, str + 1);
- }
-}
-
-bool UnitTestOptions::MatchesFilter(
- const std::string& name, const char* filter) {
- const char *cur_pattern = filter;
- for (;;) {
- if (PatternMatchesString(cur_pattern, name.c_str())) {
- return true;
- }
-
- // Finds the next pattern in the filter.
- cur_pattern = strchr(cur_pattern, ':');
-
- // Returns if no more pattern can be found.
- if (cur_pattern == nullptr) {
- return false;
- }
-
- // Skips the pattern separater (the ':' character).
- cur_pattern++;
- }
-}
-
-// Returns true if and only if the user-specified filter matches the test
-// suite name and the test name.
-bool UnitTestOptions::FilterMatchesTest(const std::string& test_suite_name,
- const std::string& test_name) {
- const std::string& full_name = test_suite_name + "." + test_name.c_str();
-
- // Split --gtest_filter at '-', if there is one, to separate into
- // positive filter and negative filter portions
- const char* const p = GTEST_FLAG(filter).c_str();
- const char* const dash = strchr(p, '-');
- std::string positive;
- std::string negative;
- if (dash == nullptr) {
- positive = GTEST_FLAG(filter).c_str(); // Whole string is a positive filter
- negative = "";
- } else {
- positive = std::string(p, dash); // Everything up to the dash
- negative = std::string(dash + 1); // Everything after the dash
- if (positive.empty()) {
- // Treat '-test1' as the same as '*-test1'
- positive = kUniversalFilter;
- }
- }
-
- // A filter is a colon-separated list of patterns. It matches a
- // test if any pattern in it matches the test.
- return (MatchesFilter(full_name, positive.c_str()) &&
- !MatchesFilter(full_name, negative.c_str()));
-}
-
-#if GTEST_HAS_SEH
-// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
-// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
-// This function is useful as an __except condition.
-int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
- // Google Test should handle a SEH exception if:
- // 1. the user wants it to, AND
- // 2. this is not a breakpoint exception, AND
- // 3. this is not a C++ exception (VC++ implements them via SEH,
- // apparently).
- //
- // SEH exception code for C++ exceptions.
- // (see http://support.microsoft.com/kb/185294 for more information).
- const DWORD kCxxExceptionCode = 0xe06d7363;
-
- bool should_handle = true;
-
- if (!GTEST_FLAG(catch_exceptions))
- should_handle = false;
- else if (exception_code == EXCEPTION_BREAKPOINT)
- should_handle = false;
- else if (exception_code == kCxxExceptionCode)
- should_handle = false;
-
- return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
-}
-#endif // GTEST_HAS_SEH
-
-} // namespace internal
-
-// The c'tor sets this object as the test part result reporter used by
-// Google Test. The 'result' parameter specifies where to report the
-// results. Intercepts only failures from the current thread.
-ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
- TestPartResultArray* result)
- : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
- result_(result) {
- Init();
-}
-
-// The c'tor sets this object as the test part result reporter used by
-// Google Test. The 'result' parameter specifies where to report the
-// results.
-ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
- InterceptMode intercept_mode, TestPartResultArray* result)
- : intercept_mode_(intercept_mode),
- result_(result) {
- Init();
-}
-
-void ScopedFakeTestPartResultReporter::Init() {
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
- old_reporter_ = impl->GetGlobalTestPartResultReporter();
- impl->SetGlobalTestPartResultReporter(this);
- } else {
- old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
- impl->SetTestPartResultReporterForCurrentThread(this);
- }
-}
-
-// The d'tor restores the test part result reporter used by Google Test
-// before.
-ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
- impl->SetGlobalTestPartResultReporter(old_reporter_);
- } else {
- impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
- }
-}
-
-// Increments the test part result count and remembers the result.
-// This method is from the TestPartResultReporterInterface interface.
-void ScopedFakeTestPartResultReporter::ReportTestPartResult(
- const TestPartResult& result) {
- result_->Append(result);
-}
-
-namespace internal {
-
-// Returns the type ID of ::testing::Test. We should always call this
-// instead of GetTypeId< ::testing::Test>() to get the type ID of
-// testing::Test. This is to work around a suspected linker bug when
-// using Google Test as a framework on Mac OS X. The bug causes
-// GetTypeId< ::testing::Test>() to return different values depending
-// on whether the call is from the Google Test framework itself or
-// from user test code. GetTestTypeId() is guaranteed to always
-// return the same value, as it always calls GetTypeId<>() from the
-// gtest.cc, which is within the Google Test framework.
-TypeId GetTestTypeId() {
- return GetTypeId<Test>();
-}
-
-// The value of GetTestTypeId() as seen from within the Google Test
-// library. This is solely for testing GetTestTypeId().
-extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
-
-// This predicate-formatter checks that 'results' contains a test part
-// failure of the given type and that the failure message contains the
-// given substring.
-static AssertionResult HasOneFailure(const char* /* results_expr */,
- const char* /* type_expr */,
- const char* /* substr_expr */,
- const TestPartResultArray& results,
- TestPartResult::Type type,
- const std::string& substr) {
- const std::string expected(type == TestPartResult::kFatalFailure ?
- "1 fatal failure" :
- "1 non-fatal failure");
- Message msg;
- if (results.size() != 1) {
- msg << "Expected: " << expected << "\n"
- << " Actual: " << results.size() << " failures";
- for (int i = 0; i < results.size(); i++) {
- msg << "\n" << results.GetTestPartResult(i);
- }
- return AssertionFailure() << msg;
- }
-
- const TestPartResult& r = results.GetTestPartResult(0);
- if (r.type() != type) {
- return AssertionFailure() << "Expected: " << expected << "\n"
- << " Actual:\n"
- << r;
- }
-
- if (strstr(r.message(), substr.c_str()) == nullptr) {
- return AssertionFailure() << "Expected: " << expected << " containing \""
- << substr << "\"\n"
- << " Actual:\n"
- << r;
- }
-
- return AssertionSuccess();
-}
-
-// The constructor of SingleFailureChecker remembers where to look up
-// test part results, what type of failure we expect, and what
-// substring the failure message should contain.
-SingleFailureChecker::SingleFailureChecker(const TestPartResultArray* results,
- TestPartResult::Type type,
- const std::string& substr)
- : results_(results), type_(type), substr_(substr) {}
-
-// The destructor of SingleFailureChecker verifies that the given
-// TestPartResultArray contains exactly one failure that has the given
-// type and contains the given substring. If that's not the case, a
-// non-fatal failure will be generated.
-SingleFailureChecker::~SingleFailureChecker() {
- EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
-}
-
-DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
- UnitTestImpl* unit_test) : unit_test_(unit_test) {}
-
-void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
- const TestPartResult& result) {
- unit_test_->current_test_result()->AddTestPartResult(result);
- unit_test_->listeners()->repeater()->OnTestPartResult(result);
-}
-
-DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
- UnitTestImpl* unit_test) : unit_test_(unit_test) {}
-
-void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
- const TestPartResult& result) {
- unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
-}
-
-// Returns the global test part result reporter.
-TestPartResultReporterInterface*
-UnitTestImpl::GetGlobalTestPartResultReporter() {
- internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
- return global_test_part_result_repoter_;
-}
-
-// Sets the global test part result reporter.
-void UnitTestImpl::SetGlobalTestPartResultReporter(
- TestPartResultReporterInterface* reporter) {
- internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
- global_test_part_result_repoter_ = reporter;
-}
-
-// Returns the test part result reporter for the current thread.
-TestPartResultReporterInterface*
-UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
- return per_thread_test_part_result_reporter_.get();
-}
-
-// Sets the test part result reporter for the current thread.
-void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
- TestPartResultReporterInterface* reporter) {
- per_thread_test_part_result_reporter_.set(reporter);
-}
-
-// Gets the number of successful test suites.
-int UnitTestImpl::successful_test_suite_count() const {
- return CountIf(test_suites_, TestSuitePassed);
-}
-
-// Gets the number of failed test suites.
-int UnitTestImpl::failed_test_suite_count() const {
- return CountIf(test_suites_, TestSuiteFailed);
-}
-
-// Gets the number of all test suites.
-int UnitTestImpl::total_test_suite_count() const {
- return static_cast<int>(test_suites_.size());
-}
-
-// Gets the number of all test suites that contain at least one test
-// that should run.
-int UnitTestImpl::test_suite_to_run_count() const {
- return CountIf(test_suites_, ShouldRunTestSuite);
-}
-
-// Gets the number of successful tests.
-int UnitTestImpl::successful_test_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::successful_test_count);
-}
-
-// Gets the number of skipped tests.
-int UnitTestImpl::skipped_test_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::skipped_test_count);
-}
-
-// Gets the number of failed tests.
-int UnitTestImpl::failed_test_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::failed_test_count);
-}
-
-// Gets the number of disabled tests that will be reported in the XML report.
-int UnitTestImpl::reportable_disabled_test_count() const {
- return SumOverTestSuiteList(test_suites_,
- &TestSuite::reportable_disabled_test_count);
-}
-
-// Gets the number of disabled tests.
-int UnitTestImpl::disabled_test_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::disabled_test_count);
-}
-
-// Gets the number of tests to be printed in the XML report.
-int UnitTestImpl::reportable_test_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::reportable_test_count);
-}
-
-// Gets the number of all tests.
-int UnitTestImpl::total_test_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::total_test_count);
-}
-
-// Gets the number of tests that should run.
-int UnitTestImpl::test_to_run_count() const {
- return SumOverTestSuiteList(test_suites_, &TestSuite::test_to_run_count);
-}
-
-// Returns the current OS stack trace as an std::string.
-//
-// The maximum number of stack frames to be included is specified by
-// the gtest_stack_trace_depth flag. The skip_count parameter
-// specifies the number of top frames to be skipped, which doesn't
-// count against the number of frames to be included.
-//
-// For example, if Foo() calls Bar(), which in turn calls
-// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
-// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
-std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
- return os_stack_trace_getter()->CurrentStackTrace(
- static_cast<int>(GTEST_FLAG(stack_trace_depth)),
- skip_count + 1
- // Skips the user-specified number of frames plus this function
- // itself.
- ); // NOLINT
-}
-
-// Returns the current time in milliseconds.
-TimeInMillis GetTimeInMillis() {
-#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
- // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
- // http://analogous.blogspot.com/2005/04/epoch.html
- const TimeInMillis kJavaEpochToWinFileTimeDelta =
- static_cast<TimeInMillis>(116444736UL) * 100000UL;
- const DWORD kTenthMicrosInMilliSecond = 10000;
-
- SYSTEMTIME now_systime;
- FILETIME now_filetime;
- ULARGE_INTEGER now_int64;
- GetSystemTime(&now_systime);
- if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
- now_int64.LowPart = now_filetime.dwLowDateTime;
- now_int64.HighPart = now_filetime.dwHighDateTime;
- now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
- kJavaEpochToWinFileTimeDelta;
- return now_int64.QuadPart;
- }
- return 0;
-#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
- __timeb64 now;
-
- // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
- // (deprecated function) there.
- GTEST_DISABLE_MSC_DEPRECATED_PUSH_()
- _ftime64(&now);
- GTEST_DISABLE_MSC_DEPRECATED_POP_()
-
- return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
-#elif GTEST_HAS_GETTIMEOFDAY_
- struct timeval now;
- gettimeofday(&now, nullptr);
- return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
-#else
-# error "Don't know how to get the current time on your system."
-#endif
-}
-
-// Utilities
-
-// class String.
-
-#if GTEST_OS_WINDOWS_MOBILE
-// Creates a UTF-16 wide string from the given ANSI string, allocating
-// memory using new. The caller is responsible for deleting the return
-// value using delete[]. Returns the wide string, or NULL if the
-// input is NULL.
-LPCWSTR String::AnsiToUtf16(const char* ansi) {
- if (!ansi) return nullptr;
- const int length = strlen(ansi);
- const int unicode_length =
- MultiByteToWideChar(CP_ACP, 0, ansi, length, nullptr, 0);
- WCHAR* unicode = new WCHAR[unicode_length + 1];
- MultiByteToWideChar(CP_ACP, 0, ansi, length,
- unicode, unicode_length);
- unicode[unicode_length] = 0;
- return unicode;
-}
-
-// Creates an ANSI string from the given wide string, allocating
-// memory using new. The caller is responsible for deleting the return
-// value using delete[]. Returns the ANSI string, or NULL if the
-// input is NULL.
-const char* String::Utf16ToAnsi(LPCWSTR utf16_str) {
- if (!utf16_str) return nullptr;
- const int ansi_length = WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, nullptr,
- 0, nullptr, nullptr);
- char* ansi = new char[ansi_length + 1];
- WideCharToMultiByte(CP_ACP, 0, utf16_str, -1, ansi, ansi_length, nullptr,
- nullptr);
- ansi[ansi_length] = 0;
- return ansi;
-}
-
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-// Compares two C strings. Returns true if and only if they have the same
-// content.
-//
-// Unlike strcmp(), this function can handle NULL argument(s). A NULL
-// C string is considered different to any non-NULL C string,
-// including the empty string.
-bool String::CStringEquals(const char * lhs, const char * rhs) {
- if (lhs == nullptr) return rhs == nullptr;
-
- if (rhs == nullptr) return false;
-
- return strcmp(lhs, rhs) == 0;
-}
-
-#if GTEST_HAS_STD_WSTRING
-
-// Converts an array of wide chars to a narrow string using the UTF-8
-// encoding, and streams the result to the given Message object.
-static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
- Message* msg) {
- for (size_t i = 0; i != length; ) { // NOLINT
- if (wstr[i] != L'\0') {
- *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
- while (i != length && wstr[i] != L'\0')
- i++;
- } else {
- *msg << '\0';
- i++;
- }
- }
-}
-
-#endif // GTEST_HAS_STD_WSTRING
-
-void SplitString(const ::std::string& str, char delimiter,
- ::std::vector< ::std::string>* dest) {
- ::std::vector< ::std::string> parsed;
- ::std::string::size_type pos = 0;
- while (::testing::internal::AlwaysTrue()) {
- const ::std::string::size_type colon = str.find(delimiter, pos);
- if (colon == ::std::string::npos) {
- parsed.push_back(str.substr(pos));
- break;
- } else {
- parsed.push_back(str.substr(pos, colon - pos));
- pos = colon + 1;
- }
- }
- dest->swap(parsed);
-}
-
-} // namespace internal
-
-// Constructs an empty Message.
-// We allocate the stringstream separately because otherwise each use of
-// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
-// stack frame leading to huge stack frames in some cases; gcc does not reuse
-// the stack space.
-Message::Message() : ss_(new ::std::stringstream) {
- // By default, we want there to be enough precision when printing
- // a double to a Message.
- *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
-}
-
-// These two overloads allow streaming a wide C string to a Message
-// using the UTF-8 encoding.
-Message& Message::operator <<(const wchar_t* wide_c_str) {
- return *this << internal::String::ShowWideCString(wide_c_str);
-}
-Message& Message::operator <<(wchar_t* wide_c_str) {
- return *this << internal::String::ShowWideCString(wide_c_str);
-}
-
-#if GTEST_HAS_STD_WSTRING
-// Converts the given wide string to a narrow string using the UTF-8
-// encoding, and streams the result to this Message object.
-Message& Message::operator <<(const ::std::wstring& wstr) {
- internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
- return *this;
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-// Gets the text streamed to this object so far as an std::string.
-// Each '\0' character in the buffer is replaced with "\\0".
-std::string Message::GetString() const {
- return internal::StringStreamToString(ss_.get());
-}
-
-// AssertionResult constructors.
-// Used in EXPECT_TRUE/FALSE(assertion_result).
-AssertionResult::AssertionResult(const AssertionResult& other)
- : success_(other.success_),
- message_(other.message_.get() != nullptr
- ? new ::std::string(*other.message_)
- : static_cast< ::std::string*>(nullptr)) {}
-
-// Swaps two AssertionResults.
-void AssertionResult::swap(AssertionResult& other) {
- using std::swap;
- swap(success_, other.success_);
- swap(message_, other.message_);
-}
-
-// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
-AssertionResult AssertionResult::operator!() const {
- AssertionResult negation(!success_);
- if (message_.get() != nullptr) negation << *message_;
- return negation;
-}
-
-// Makes a successful assertion result.
-AssertionResult AssertionSuccess() {
- return AssertionResult(true);
-}
-
-// Makes a failed assertion result.
-AssertionResult AssertionFailure() {
- return AssertionResult(false);
-}
-
-// Makes a failed assertion result with the given failure message.
-// Deprecated; use AssertionFailure() << message.
-AssertionResult AssertionFailure(const Message& message) {
- return AssertionFailure() << message;
-}
-
-namespace internal {
-
-namespace edit_distance {
-std::vector<EditType> CalculateOptimalEdits(const std::vector<size_t>& left,
- const std::vector<size_t>& right) {
- std::vector<std::vector<double> > costs(
- left.size() + 1, std::vector<double>(right.size() + 1));
- std::vector<std::vector<EditType> > best_move(
- left.size() + 1, std::vector<EditType>(right.size() + 1));
-
- // Populate for empty right.
- for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
- costs[l_i][0] = static_cast<double>(l_i);
- best_move[l_i][0] = kRemove;
- }
- // Populate for empty left.
- for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
- costs[0][r_i] = static_cast<double>(r_i);
- best_move[0][r_i] = kAdd;
- }
-
- for (size_t l_i = 0; l_i < left.size(); ++l_i) {
- for (size_t r_i = 0; r_i < right.size(); ++r_i) {
- if (left[l_i] == right[r_i]) {
- // Found a match. Consume it.
- costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
- best_move[l_i + 1][r_i + 1] = kMatch;
- continue;
- }
-
- const double add = costs[l_i + 1][r_i];
- const double remove = costs[l_i][r_i + 1];
- const double replace = costs[l_i][r_i];
- if (add < remove && add < replace) {
- costs[l_i + 1][r_i + 1] = add + 1;
- best_move[l_i + 1][r_i + 1] = kAdd;
- } else if (remove < add && remove < replace) {
- costs[l_i + 1][r_i + 1] = remove + 1;
- best_move[l_i + 1][r_i + 1] = kRemove;
- } else {
- // We make replace a little more expensive than add/remove to lower
- // their priority.
- costs[l_i + 1][r_i + 1] = replace + 1.00001;
- best_move[l_i + 1][r_i + 1] = kReplace;
- }
- }
- }
-
- // Reconstruct the best path. We do it in reverse order.
- std::vector<EditType> best_path;
- for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
- EditType move = best_move[l_i][r_i];
- best_path.push_back(move);
- l_i -= move != kAdd;
- r_i -= move != kRemove;
- }
- std::reverse(best_path.begin(), best_path.end());
- return best_path;
-}
-
-namespace {
-
-// Helper class to convert string into ids with deduplication.
-class InternalStrings {
- public:
- size_t GetId(const std::string& str) {
- IdMap::iterator it = ids_.find(str);
- if (it != ids_.end()) return it->second;
- size_t id = ids_.size();
- return ids_[str] = id;
- }
-
- private:
- typedef std::map<std::string, size_t> IdMap;
- IdMap ids_;
-};
-
-} // namespace
-
-std::vector<EditType> CalculateOptimalEdits(
- const std::vector<std::string>& left,
- const std::vector<std::string>& right) {
- std::vector<size_t> left_ids, right_ids;
- {
- InternalStrings intern_table;
- for (size_t i = 0; i < left.size(); ++i) {
- left_ids.push_back(intern_table.GetId(left[i]));
- }
- for (size_t i = 0; i < right.size(); ++i) {
- right_ids.push_back(intern_table.GetId(right[i]));
- }
- }
- return CalculateOptimalEdits(left_ids, right_ids);
-}
-
-namespace {
-
-// Helper class that holds the state for one hunk and prints it out to the
-// stream.
-// It reorders adds/removes when possible to group all removes before all
-// adds. It also adds the hunk header before printint into the stream.
-class Hunk {
- public:
- Hunk(size_t left_start, size_t right_start)
- : left_start_(left_start),
- right_start_(right_start),
- adds_(),
- removes_(),
- common_() {}
-
- void PushLine(char edit, const char* line) {
- switch (edit) {
- case ' ':
- ++common_;
- FlushEdits();
- hunk_.push_back(std::make_pair(' ', line));
- break;
- case '-':
- ++removes_;
- hunk_removes_.push_back(std::make_pair('-', line));
- break;
- case '+':
- ++adds_;
- hunk_adds_.push_back(std::make_pair('+', line));
- break;
- }
- }
-
- void PrintTo(std::ostream* os) {
- PrintHeader(os);
- FlushEdits();
- for (std::list<std::pair<char, const char*> >::const_iterator it =
- hunk_.begin();
- it != hunk_.end(); ++it) {
- *os << it->first << it->second << "\n";
- }
- }
-
- bool has_edits() const { return adds_ || removes_; }
-
- private:
- void FlushEdits() {
- hunk_.splice(hunk_.end(), hunk_removes_);
- hunk_.splice(hunk_.end(), hunk_adds_);
- }
-
- // Print a unified diff header for one hunk.
- // The format is
- // "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
- // where the left/right parts are omitted if unnecessary.
- void PrintHeader(std::ostream* ss) const {
- *ss << "@@ ";
- if (removes_) {
- *ss << "-" << left_start_ << "," << (removes_ + common_);
- }
- if (removes_ && adds_) {
- *ss << " ";
- }
- if (adds_) {
- *ss << "+" << right_start_ << "," << (adds_ + common_);
- }
- *ss << " @@\n";
- }
-
- size_t left_start_, right_start_;
- size_t adds_, removes_, common_;
- std::list<std::pair<char, const char*> > hunk_, hunk_adds_, hunk_removes_;
-};
-
-} // namespace
-
-// Create a list of diff hunks in Unified diff format.
-// Each hunk has a header generated by PrintHeader above plus a body with
-// lines prefixed with ' ' for no change, '-' for deletion and '+' for
-// addition.
-// 'context' represents the desired unchanged prefix/suffix around the diff.
-// If two hunks are close enough that their contexts overlap, then they are
-// joined into one hunk.
-std::string CreateUnifiedDiff(const std::vector<std::string>& left,
- const std::vector<std::string>& right,
- size_t context) {
- const std::vector<EditType> edits = CalculateOptimalEdits(left, right);
-
- size_t l_i = 0, r_i = 0, edit_i = 0;
- std::stringstream ss;
- while (edit_i < edits.size()) {
- // Find first edit.
- while (edit_i < edits.size() && edits[edit_i] == kMatch) {
- ++l_i;
- ++r_i;
- ++edit_i;
- }
-
- // Find the first line to include in the hunk.
- const size_t prefix_context = std::min(l_i, context);
- Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
- for (size_t i = prefix_context; i > 0; --i) {
- hunk.PushLine(' ', left[l_i - i].c_str());
- }
-
- // Iterate the edits until we found enough suffix for the hunk or the input
- // is over.
- size_t n_suffix = 0;
- for (; edit_i < edits.size(); ++edit_i) {
- if (n_suffix >= context) {
- // Continue only if the next hunk is very close.
- auto it = edits.begin() + static_cast<int>(edit_i);
- while (it != edits.end() && *it == kMatch) ++it;
- if (it == edits.end() ||
- static_cast<size_t>(it - edits.begin()) - edit_i >= context) {
- // There is no next edit or it is too far away.
- break;
- }
- }
-
- EditType edit = edits[edit_i];
- // Reset count when a non match is found.
- n_suffix = edit == kMatch ? n_suffix + 1 : 0;
-
- if (edit == kMatch || edit == kRemove || edit == kReplace) {
- hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
- }
- if (edit == kAdd || edit == kReplace) {
- hunk.PushLine('+', right[r_i].c_str());
- }
-
- // Advance indices, depending on edit type.
- l_i += edit != kAdd;
- r_i += edit != kRemove;
- }
-
- if (!hunk.has_edits()) {
- // We are done. We don't want this hunk.
- break;
- }
-
- hunk.PrintTo(&ss);
- }
- return ss.str();
-}
-
-} // namespace edit_distance
-
-namespace {
-
-// The string representation of the values received in EqFailure() are already
-// escaped. Split them on escaped '\n' boundaries. Leave all other escaped
-// characters the same.
-std::vector<std::string> SplitEscapedString(const std::string& str) {
- std::vector<std::string> lines;
- size_t start = 0, end = str.size();
- if (end > 2 && str[0] == '"' && str[end - 1] == '"') {
- ++start;
- --end;
- }
- bool escaped = false;
- for (size_t i = start; i + 1 < end; ++i) {
- if (escaped) {
- escaped = false;
- if (str[i] == 'n') {
- lines.push_back(str.substr(start, i - start - 1));
- start = i + 1;
- }
- } else {
- escaped = str[i] == '\\';
- }
- }
- lines.push_back(str.substr(start, end - start));
- return lines;
-}
-
-} // namespace
-
-// Constructs and returns the message for an equality assertion
-// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
-//
-// The first four parameters are the expressions used in the assertion
-// and their values, as strings. For example, for ASSERT_EQ(foo, bar)
-// where foo is 5 and bar is 6, we have:
-//
-// lhs_expression: "foo"
-// rhs_expression: "bar"
-// lhs_value: "5"
-// rhs_value: "6"
-//
-// The ignoring_case parameter is true if and only if the assertion is a
-// *_STRCASEEQ*. When it's true, the string "Ignoring case" will
-// be inserted into the message.
-AssertionResult EqFailure(const char* lhs_expression,
- const char* rhs_expression,
- const std::string& lhs_value,
- const std::string& rhs_value,
- bool ignoring_case) {
- Message msg;
- msg << "Expected equality of these values:";
- msg << "\n " << lhs_expression;
- if (lhs_value != lhs_expression) {
- msg << "\n Which is: " << lhs_value;
- }
- msg << "\n " << rhs_expression;
- if (rhs_value != rhs_expression) {
- msg << "\n Which is: " << rhs_value;
- }
-
- if (ignoring_case) {
- msg << "\nIgnoring case";
- }
-
- if (!lhs_value.empty() && !rhs_value.empty()) {
- const std::vector<std::string> lhs_lines =
- SplitEscapedString(lhs_value);
- const std::vector<std::string> rhs_lines =
- SplitEscapedString(rhs_value);
- if (lhs_lines.size() > 1 || rhs_lines.size() > 1) {
- msg << "\nWith diff:\n"
- << edit_distance::CreateUnifiedDiff(lhs_lines, rhs_lines);
- }
- }
-
- return AssertionFailure() << msg;
-}
-
-// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
-std::string GetBoolAssertionFailureMessage(
- const AssertionResult& assertion_result,
- const char* expression_text,
- const char* actual_predicate_value,
- const char* expected_predicate_value) {
- const char* actual_message = assertion_result.message();
- Message msg;
- msg << "Value of: " << expression_text
- << "\n Actual: " << actual_predicate_value;
- if (actual_message[0] != '\0')
- msg << " (" << actual_message << ")";
- msg << "\nExpected: " << expected_predicate_value;
- return msg.GetString();
-}
-
-// Helper function for implementing ASSERT_NEAR.
-AssertionResult DoubleNearPredFormat(const char* expr1,
- const char* expr2,
- const char* abs_error_expr,
- double val1,
- double val2,
- double abs_error) {
- const double diff = fabs(val1 - val2);
- if (diff <= abs_error) return AssertionSuccess();
-
- return AssertionFailure()
- << "The difference between " << expr1 << " and " << expr2
- << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
- << expr1 << " evaluates to " << val1 << ",\n"
- << expr2 << " evaluates to " << val2 << ", and\n"
- << abs_error_expr << " evaluates to " << abs_error << ".";
-}
-
-
-// Helper template for implementing FloatLE() and DoubleLE().
-template <typename RawType>
-AssertionResult FloatingPointLE(const char* expr1,
- const char* expr2,
- RawType val1,
- RawType val2) {
- // Returns success if val1 is less than val2,
- if (val1 < val2) {
- return AssertionSuccess();
- }
-
- // or if val1 is almost equal to val2.
- const FloatingPoint<RawType> lhs(val1), rhs(val2);
- if (lhs.AlmostEquals(rhs)) {
- return AssertionSuccess();
- }
-
- // Note that the above two checks will both fail if either val1 or
- // val2 is NaN, as the IEEE floating-point standard requires that
- // any predicate involving a NaN must return false.
-
- ::std::stringstream val1_ss;
- val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
- << val1;
-
- ::std::stringstream val2_ss;
- val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
- << val2;
-
- return AssertionFailure()
- << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
- << " Actual: " << StringStreamToString(&val1_ss) << " vs "
- << StringStreamToString(&val2_ss);
-}
-
-} // namespace internal
-
-// Asserts that val1 is less than, or almost equal to, val2. Fails
-// otherwise. In particular, it fails if either val1 or val2 is NaN.
-AssertionResult FloatLE(const char* expr1, const char* expr2,
- float val1, float val2) {
- return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
-}
-
-// Asserts that val1 is less than, or almost equal to, val2. Fails
-// otherwise. In particular, it fails if either val1 or val2 is NaN.
-AssertionResult DoubleLE(const char* expr1, const char* expr2,
- double val1, double val2) {
- return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
-}
-
-namespace internal {
-
-// The helper function for {ASSERT|EXPECT}_EQ with int or enum
-// arguments.
-AssertionResult CmpHelperEQ(const char* lhs_expression,
- const char* rhs_expression,
- BiggestInt lhs,
- BiggestInt rhs) {
- if (lhs == rhs) {
- return AssertionSuccess();
- }
-
- return EqFailure(lhs_expression,
- rhs_expression,
- FormatForComparisonFailureMessage(lhs, rhs),
- FormatForComparisonFailureMessage(rhs, lhs),
- false);
-}
-
-// A macro for implementing the helper functions needed to implement
-// ASSERT_?? and EXPECT_?? with integer or enum arguments. It is here
-// just to avoid copy-and-paste of similar code.
-#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
-AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
- BiggestInt val1, BiggestInt val2) {\
- if (val1 op val2) {\
- return AssertionSuccess();\
- } else {\
- return AssertionFailure() \
- << "Expected: (" << expr1 << ") " #op " (" << expr2\
- << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
- << " vs " << FormatForComparisonFailureMessage(val2, val1);\
- }\
-}
-
-// Implements the helper function for {ASSERT|EXPECT}_NE with int or
-// enum arguments.
-GTEST_IMPL_CMP_HELPER_(NE, !=)
-// Implements the helper function for {ASSERT|EXPECT}_LE with int or
-// enum arguments.
-GTEST_IMPL_CMP_HELPER_(LE, <=)
-// Implements the helper function for {ASSERT|EXPECT}_LT with int or
-// enum arguments.
-GTEST_IMPL_CMP_HELPER_(LT, < )
-// Implements the helper function for {ASSERT|EXPECT}_GE with int or
-// enum arguments.
-GTEST_IMPL_CMP_HELPER_(GE, >=)
-// Implements the helper function for {ASSERT|EXPECT}_GT with int or
-// enum arguments.
-GTEST_IMPL_CMP_HELPER_(GT, > )
-
-#undef GTEST_IMPL_CMP_HELPER_
-
-// The helper function for {ASSERT|EXPECT}_STREQ.
-AssertionResult CmpHelperSTREQ(const char* lhs_expression,
- const char* rhs_expression,
- const char* lhs,
- const char* rhs) {
- if (String::CStringEquals(lhs, rhs)) {
- return AssertionSuccess();
- }
-
- return EqFailure(lhs_expression,
- rhs_expression,
- PrintToString(lhs),
- PrintToString(rhs),
- false);
-}
-
-// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
-AssertionResult CmpHelperSTRCASEEQ(const char* lhs_expression,
- const char* rhs_expression,
- const char* lhs,
- const char* rhs) {
- if (String::CaseInsensitiveCStringEquals(lhs, rhs)) {
- return AssertionSuccess();
- }
-
- return EqFailure(lhs_expression,
- rhs_expression,
- PrintToString(lhs),
- PrintToString(rhs),
- true);
-}
-
-// The helper function for {ASSERT|EXPECT}_STRNE.
-AssertionResult CmpHelperSTRNE(const char* s1_expression,
- const char* s2_expression,
- const char* s1,
- const char* s2) {
- if (!String::CStringEquals(s1, s2)) {
- return AssertionSuccess();
- } else {
- return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: \""
- << s1 << "\" vs \"" << s2 << "\"";
- }
-}
-
-// The helper function for {ASSERT|EXPECT}_STRCASENE.
-AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
- const char* s2_expression,
- const char* s1,
- const char* s2) {
- if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
- return AssertionSuccess();
- } else {
- return AssertionFailure()
- << "Expected: (" << s1_expression << ") != ("
- << s2_expression << ") (ignoring case), actual: \""
- << s1 << "\" vs \"" << s2 << "\"";
- }
-}
-
-} // namespace internal
-
-namespace {
-
-// Helper functions for implementing IsSubString() and IsNotSubstring().
-
-// This group of overloaded functions return true if and only if needle
-// is a substring of haystack. NULL is considered a substring of
-// itself only.
-
-bool IsSubstringPred(const char* needle, const char* haystack) {
- if (needle == nullptr || haystack == nullptr) return needle == haystack;
-
- return strstr(haystack, needle) != nullptr;
-}
-
-bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
- if (needle == nullptr || haystack == nullptr) return needle == haystack;
-
- return wcsstr(haystack, needle) != nullptr;
-}
-
-// StringType here can be either ::std::string or ::std::wstring.
-template <typename StringType>
-bool IsSubstringPred(const StringType& needle,
- const StringType& haystack) {
- return haystack.find(needle) != StringType::npos;
-}
-
-// This function implements either IsSubstring() or IsNotSubstring(),
-// depending on the value of the expected_to_be_substring parameter.
-// StringType here can be const char*, const wchar_t*, ::std::string,
-// or ::std::wstring.
-template <typename StringType>
-AssertionResult IsSubstringImpl(
- bool expected_to_be_substring,
- const char* needle_expr, const char* haystack_expr,
- const StringType& needle, const StringType& haystack) {
- if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
- return AssertionSuccess();
-
- const bool is_wide_string = sizeof(needle[0]) > 1;
- const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
- return AssertionFailure()
- << "Value of: " << needle_expr << "\n"
- << " Actual: " << begin_string_quote << needle << "\"\n"
- << "Expected: " << (expected_to_be_substring ? "" : "not ")
- << "a substring of " << haystack_expr << "\n"
- << "Which is: " << begin_string_quote << haystack << "\"";
-}
-
-} // namespace
-
-// IsSubstring() and IsNotSubstring() check whether needle is a
-// substring of haystack (NULL is considered a substring of itself
-// only), and return an appropriate error message when they fail.
-
-AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const char* needle, const char* haystack) {
- return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
-}
-
-AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const wchar_t* needle, const wchar_t* haystack) {
- return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
-}
-
-AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const char* needle, const char* haystack) {
- return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
-}
-
-AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const wchar_t* needle, const wchar_t* haystack) {
- return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
-}
-
-AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::string& needle, const ::std::string& haystack) {
- return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
-}
-
-AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::string& needle, const ::std::string& haystack) {
- return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
-}
-
-#if GTEST_HAS_STD_WSTRING
-AssertionResult IsSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::wstring& needle, const ::std::wstring& haystack) {
- return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
-}
-
-AssertionResult IsNotSubstring(
- const char* needle_expr, const char* haystack_expr,
- const ::std::wstring& needle, const ::std::wstring& haystack) {
- return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-namespace internal {
-
-#if GTEST_OS_WINDOWS
-
-namespace {
-
-// Helper function for IsHRESULT{SuccessFailure} predicates
-AssertionResult HRESULTFailureHelper(const char* expr,
- const char* expected,
- long hr) { // NOLINT
-# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_TV_TITLE
-
- // Windows CE doesn't support FormatMessage.
- const char error_text[] = "";
-
-# else
-
- // Looks up the human-readable system message for the HRESULT code
- // and since we're not passing any params to FormatMessage, we don't
- // want inserts expanded.
- const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS;
- const DWORD kBufSize = 4096;
- // Gets the system's human readable message string for this HRESULT.
- char error_text[kBufSize] = { '\0' };
- DWORD message_length = ::FormatMessageA(kFlags,
- 0, // no source, we're asking system
- static_cast<DWORD>(hr), // the error
- 0, // no line width restrictions
- error_text, // output buffer
- kBufSize, // buf size
- nullptr); // no arguments for inserts
- // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
- for (; message_length && IsSpace(error_text[message_length - 1]);
- --message_length) {
- error_text[message_length - 1] = '\0';
- }
-
-# endif // GTEST_OS_WINDOWS_MOBILE
-
- const std::string error_hex("0x" + String::FormatHexInt(hr));
- return ::testing::AssertionFailure()
- << "Expected: " << expr << " " << expected << ".\n"
- << " Actual: " << error_hex << " " << error_text << "\n";
-}
-
-} // namespace
-
-AssertionResult IsHRESULTSuccess(const char* expr, long hr) { // NOLINT
- if (SUCCEEDED(hr)) {
- return AssertionSuccess();
- }
- return HRESULTFailureHelper(expr, "succeeds", hr);
-}
-
-AssertionResult IsHRESULTFailure(const char* expr, long hr) { // NOLINT
- if (FAILED(hr)) {
- return AssertionSuccess();
- }
- return HRESULTFailureHelper(expr, "fails", hr);
-}
-
-#endif // GTEST_OS_WINDOWS
-
-// Utility functions for encoding Unicode text (wide strings) in
-// UTF-8.
-
-// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8
-// like this:
-//
-// Code-point length Encoding
-// 0 - 7 bits 0xxxxxxx
-// 8 - 11 bits 110xxxxx 10xxxxxx
-// 12 - 16 bits 1110xxxx 10xxxxxx 10xxxxxx
-// 17 - 21 bits 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-
-// The maximum code-point a one-byte UTF-8 sequence can represent.
-const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) << 7) - 1;
-
-// The maximum code-point a two-byte UTF-8 sequence can represent.
-const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
-
-// The maximum code-point a three-byte UTF-8 sequence can represent.
-const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
-
-// The maximum code-point a four-byte UTF-8 sequence can represent.
-const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
-
-// Chops off the n lowest bits from a bit pattern. Returns the n
-// lowest bits. As a side effect, the original bit pattern will be
-// shifted to the right by n bits.
-inline UInt32 ChopLowBits(UInt32* bits, int n) {
- const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
- *bits >>= n;
- return low_bits;
-}
-
-// Converts a Unicode code point to a narrow string in UTF-8 encoding.
-// code_point parameter is of type UInt32 because wchar_t may not be
-// wide enough to contain a code point.
-// If the code_point is not a valid Unicode code point
-// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
-// to "(Invalid Unicode 0xXXXXXXXX)".
-std::string CodePointToUtf8(UInt32 code_point) {
- if (code_point > kMaxCodePoint4) {
- return "(Invalid Unicode 0x" + String::FormatHexUInt32(code_point) + ")";
- }
-
- char str[5]; // Big enough for the largest valid code point.
- if (code_point <= kMaxCodePoint1) {
- str[1] = '\0';
- str[0] = static_cast<char>(code_point); // 0xxxxxxx
- } else if (code_point <= kMaxCodePoint2) {
- str[2] = '\0';
- str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
- str[0] = static_cast<char>(0xC0 | code_point); // 110xxxxx
- } else if (code_point <= kMaxCodePoint3) {
- str[3] = '\0';
- str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
- str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
- str[0] = static_cast<char>(0xE0 | code_point); // 1110xxxx
- } else { // code_point <= kMaxCodePoint4
- str[4] = '\0';
- str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
- str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
- str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6)); // 10xxxxxx
- str[0] = static_cast<char>(0xF0 | code_point); // 11110xxx
- }
- return str;
-}
-
-// The following two functions only make sense if the system
-// uses UTF-16 for wide string encoding. All supported systems
-// with 16 bit wchar_t (Windows, Cygwin) do use UTF-16.
-
-// Determines if the arguments constitute UTF-16 surrogate pair
-// and thus should be combined into a single Unicode code point
-// using CreateCodePointFromUtf16SurrogatePair.
-inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
- return sizeof(wchar_t) == 2 &&
- (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
-}
-
-// Creates a Unicode code point from UTF16 surrogate pair.
-inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
- wchar_t second) {
- const auto first_u = static_cast<UInt32>(first);
- const auto second_u = static_cast<UInt32>(second);
- const UInt32 mask = (1 << 10) - 1;
- return (sizeof(wchar_t) == 2)
- ? (((first_u & mask) << 10) | (second_u & mask)) + 0x10000
- :
- // This function should not be called when the condition is
- // false, but we provide a sensible default in case it is.
- first_u;
-}
-
-// Converts a wide string to a narrow string in UTF-8 encoding.
-// The wide string is assumed to have the following encoding:
-// UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin)
-// UTF-32 if sizeof(wchar_t) == 4 (on Linux)
-// Parameter str points to a null-terminated wide string.
-// Parameter num_chars may additionally limit the number
-// of wchar_t characters processed. -1 is used when the entire string
-// should be processed.
-// If the string contains code points that are not valid Unicode code points
-// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
-// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
-// and contains invalid UTF-16 surrogate pairs, values in those pairs
-// will be encoded as individual Unicode characters from Basic Normal Plane.
-std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
- if (num_chars == -1)
- num_chars = static_cast<int>(wcslen(str));
-
- ::std::stringstream stream;
- for (int i = 0; i < num_chars; ++i) {
- UInt32 unicode_code_point;
-
- if (str[i] == L'\0') {
- break;
- } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
- unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
- str[i + 1]);
- i++;
- } else {
- unicode_code_point = static_cast<UInt32>(str[i]);
- }
-
- stream << CodePointToUtf8(unicode_code_point);
- }
- return StringStreamToString(&stream);
-}
-
-// Converts a wide C string to an std::string using the UTF-8 encoding.
-// NULL will be converted to "(null)".
-std::string String::ShowWideCString(const wchar_t * wide_c_str) {
- if (wide_c_str == nullptr) return "(null)";
-
- return internal::WideStringToUtf8(wide_c_str, -1);
-}
-
-// Compares two wide C strings. Returns true if and only if they have the
-// same content.
-//
-// Unlike wcscmp(), this function can handle NULL argument(s). A NULL
-// C string is considered different to any non-NULL C string,
-// including the empty string.
-bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
- if (lhs == nullptr) return rhs == nullptr;
-
- if (rhs == nullptr) return false;
-
- return wcscmp(lhs, rhs) == 0;
-}
-
-// Helper function for *_STREQ on wide strings.
-AssertionResult CmpHelperSTREQ(const char* lhs_expression,
- const char* rhs_expression,
- const wchar_t* lhs,
- const wchar_t* rhs) {
- if (String::WideCStringEquals(lhs, rhs)) {
- return AssertionSuccess();
- }
-
- return EqFailure(lhs_expression,
- rhs_expression,
- PrintToString(lhs),
- PrintToString(rhs),
- false);
-}
-
-// Helper function for *_STRNE on wide strings.
-AssertionResult CmpHelperSTRNE(const char* s1_expression,
- const char* s2_expression,
- const wchar_t* s1,
- const wchar_t* s2) {
- if (!String::WideCStringEquals(s1, s2)) {
- return AssertionSuccess();
- }
-
- return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: "
- << PrintToString(s1)
- << " vs " << PrintToString(s2);
-}
-
-// Compares two C strings, ignoring case. Returns true if and only if they have
-// the same content.
-//
-// Unlike strcasecmp(), this function can handle NULL argument(s). A
-// NULL C string is considered different to any non-NULL C string,
-// including the empty string.
-bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
- if (lhs == nullptr) return rhs == nullptr;
- if (rhs == nullptr) return false;
- return posix::StrCaseCmp(lhs, rhs) == 0;
-}
-
-// Compares two wide C strings, ignoring case. Returns true if and only if they
-// have the same content.
-//
-// Unlike wcscasecmp(), this function can handle NULL argument(s).
-// A NULL C string is considered different to any non-NULL wide C string,
-// including the empty string.
-// NB: The implementations on different platforms slightly differ.
-// On windows, this method uses _wcsicmp which compares according to LC_CTYPE
-// environment variable. On GNU platform this method uses wcscasecmp
-// which compares according to LC_CTYPE category of the current locale.
-// On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
-// current locale.
-bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
- const wchar_t* rhs) {
- if (lhs == nullptr) return rhs == nullptr;
-
- if (rhs == nullptr) return false;
-
-#if GTEST_OS_WINDOWS
- return _wcsicmp(lhs, rhs) == 0;
-#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
- return wcscasecmp(lhs, rhs) == 0;
-#else
- // Android, Mac OS X and Cygwin don't define wcscasecmp.
- // Other unknown OSes may not define it either.
- wint_t left, right;
- do {
- left = towlower(static_cast<wint_t>(*lhs++));
- right = towlower(static_cast<wint_t>(*rhs++));
- } while (left && left == right);
- return left == right;
-#endif // OS selector
-}
-
-// Returns true if and only if str ends with the given suffix, ignoring case.
-// Any string is considered to end with an empty suffix.
-bool String::EndsWithCaseInsensitive(
- const std::string& str, const std::string& suffix) {
- const size_t str_len = str.length();
- const size_t suffix_len = suffix.length();
- return (str_len >= suffix_len) &&
- CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
- suffix.c_str());
-}
-
-// Formats an int value as "%02d".
-std::string String::FormatIntWidth2(int value) {
- std::stringstream ss;
- ss << std::setfill('0') << std::setw(2) << value;
- return ss.str();
-}
-
-// Formats an int value as "%X".
-std::string String::FormatHexUInt32(UInt32 value) {
- std::stringstream ss;
- ss << std::hex << std::uppercase << value;
- return ss.str();
-}
-
-// Formats an int value as "%X".
-std::string String::FormatHexInt(int value) {
- return FormatHexUInt32(static_cast<UInt32>(value));
-}
-
-// Formats a byte as "%02X".
-std::string String::FormatByte(unsigned char value) {
- std::stringstream ss;
- ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
- << static_cast<unsigned int>(value);
- return ss.str();
-}
-
-// Converts the buffer in a stringstream to an std::string, converting NUL
-// bytes to "\\0" along the way.
-std::string StringStreamToString(::std::stringstream* ss) {
- const ::std::string& str = ss->str();
- const char* const start = str.c_str();
- const char* const end = start + str.length();
-
- std::string result;
- result.reserve(static_cast<size_t>(2 * (end - start)));
- for (const char* ch = start; ch != end; ++ch) {
- if (*ch == '\0') {
- result += "\\0"; // Replaces NUL with "\\0";
- } else {
- result += *ch;
- }
- }
-
- return result;
-}
-
-// Appends the user-supplied message to the Google-Test-generated message.
-std::string AppendUserMessage(const std::string& gtest_msg,
- const Message& user_msg) {
- // Appends the user message if it's non-empty.
- const std::string user_msg_string = user_msg.GetString();
- if (user_msg_string.empty()) {
- return gtest_msg;
- }
-
- return gtest_msg + "\n" + user_msg_string;
-}
-
-} // namespace internal
-
-// class TestResult
-
-// Creates an empty TestResult.
-TestResult::TestResult()
- : death_test_count_(0), start_timestamp_(0), elapsed_time_(0) {}
-
-// D'tor.
-TestResult::~TestResult() {
-}
-
-// Returns the i-th test part result among all the results. i can
-// range from 0 to total_part_count() - 1. If i is not in that range,
-// aborts the program.
-const TestPartResult& TestResult::GetTestPartResult(int i) const {
- if (i < 0 || i >= total_part_count())
- internal::posix::Abort();
- return test_part_results_.at(static_cast<size_t>(i));
-}
-
-// Returns the i-th test property. i can range from 0 to
-// test_property_count() - 1. If i is not in that range, aborts the
-// program.
-const TestProperty& TestResult::GetTestProperty(int i) const {
- if (i < 0 || i >= test_property_count())
- internal::posix::Abort();
- return test_properties_.at(static_cast<size_t>(i));
-}
-
-// Clears the test part results.
-void TestResult::ClearTestPartResults() {
- test_part_results_.clear();
-}
-
-// Adds a test part result to the list.
-void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
- test_part_results_.push_back(test_part_result);
-}
-
-// Adds a test property to the list. If a property with the same key as the
-// supplied property is already represented, the value of this test_property
-// replaces the old value for that key.
-void TestResult::RecordProperty(const std::string& xml_element,
- const TestProperty& test_property) {
- if (!ValidateTestProperty(xml_element, test_property)) {
- return;
- }
- internal::MutexLock lock(&test_properites_mutex_);
- const std::vector<TestProperty>::iterator property_with_matching_key =
- std::find_if(test_properties_.begin(), test_properties_.end(),
- internal::TestPropertyKeyIs(test_property.key()));
- if (property_with_matching_key == test_properties_.end()) {
- test_properties_.push_back(test_property);
- return;
- }
- property_with_matching_key->SetValue(test_property.value());
-}
-
-// The list of reserved attributes used in the <testsuites> element of XML
-// output.
-static const char* const kReservedTestSuitesAttributes[] = {
- "disabled",
- "errors",
- "failures",
- "name",
- "random_seed",
- "tests",
- "time",
- "timestamp"
-};
-
-// The list of reserved attributes used in the <testsuite> element of XML
-// output.
-static const char* const kReservedTestSuiteAttributes[] = {
- "disabled", "errors", "failures", "name", "tests", "time", "timestamp"};
-
-// The list of reserved attributes used in the <testcase> element of XML output.
-static const char* const kReservedTestCaseAttributes[] = {
- "classname", "name", "status", "time", "type_param",
- "value_param", "file", "line"};
-
-// Use a slightly different set for allowed output to ensure existing tests can
-// still RecordProperty("result") or "RecordProperty(timestamp")
-static const char* const kReservedOutputTestCaseAttributes[] = {
- "classname", "name", "status", "time", "type_param",
- "value_param", "file", "line", "result", "timestamp"};
-
-template <int kSize>
-std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
- return std::vector<std::string>(array, array + kSize);
-}
-
-static std::vector<std::string> GetReservedAttributesForElement(
- const std::string& xml_element) {
- if (xml_element == "testsuites") {
- return ArrayAsVector(kReservedTestSuitesAttributes);
- } else if (xml_element == "testsuite") {
- return ArrayAsVector(kReservedTestSuiteAttributes);
- } else if (xml_element == "testcase") {
- return ArrayAsVector(kReservedTestCaseAttributes);
- } else {
- GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
- }
- // This code is unreachable but some compilers may not realizes that.
- return std::vector<std::string>();
-}
-
-// TODO(jdesprez): Merge the two getReserved attributes once skip is improved
-static std::vector<std::string> GetReservedOutputAttributesForElement(
- const std::string& xml_element) {
- if (xml_element == "testsuites") {
- return ArrayAsVector(kReservedTestSuitesAttributes);
- } else if (xml_element == "testsuite") {
- return ArrayAsVector(kReservedTestSuiteAttributes);
- } else if (xml_element == "testcase") {
- return ArrayAsVector(kReservedOutputTestCaseAttributes);
- } else {
- GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
- }
- // This code is unreachable but some compilers may not realizes that.
- return std::vector<std::string>();
-}
-
-static std::string FormatWordList(const std::vector<std::string>& words) {
- Message word_list;
- for (size_t i = 0; i < words.size(); ++i) {
- if (i > 0 && words.size() > 2) {
- word_list << ", ";
- }
- if (i == words.size() - 1) {
- word_list << "and ";
- }
- word_list << "'" << words[i] << "'";
- }
- return word_list.GetString();
-}
-
-static bool ValidateTestPropertyName(
- const std::string& property_name,
- const std::vector<std::string>& reserved_names) {
- if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
- reserved_names.end()) {
- ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
- << " (" << FormatWordList(reserved_names)
- << " are reserved by " << GTEST_NAME_ << ")";
- return false;
- }
- return true;
-}
-
-// Adds a failure if the key is a reserved attribute of the element named
-// xml_element. Returns true if the property is valid.
-bool TestResult::ValidateTestProperty(const std::string& xml_element,
- const TestProperty& test_property) {
- return ValidateTestPropertyName(test_property.key(),
- GetReservedAttributesForElement(xml_element));
-}
-
-// Clears the object.
-void TestResult::Clear() {
- test_part_results_.clear();
- test_properties_.clear();
- death_test_count_ = 0;
- elapsed_time_ = 0;
-}
-
-// Returns true off the test part was skipped.
-static bool TestPartSkipped(const TestPartResult& result) {
- return result.skipped();
-}
-
-// Returns true if and only if the test was skipped.
-bool TestResult::Skipped() const {
- return !Failed() && CountIf(test_part_results_, TestPartSkipped) > 0;
-}
-
-// Returns true if and only if the test failed.
-bool TestResult::Failed() const {
- for (int i = 0; i < total_part_count(); ++i) {
- if (GetTestPartResult(i).failed())
- return true;
- }
- return false;
-}
-
-// Returns true if and only if the test part fatally failed.
-static bool TestPartFatallyFailed(const TestPartResult& result) {
- return result.fatally_failed();
-}
-
-// Returns true if and only if the test fatally failed.
-bool TestResult::HasFatalFailure() const {
- return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
-}
-
-// Returns true if and only if the test part non-fatally failed.
-static bool TestPartNonfatallyFailed(const TestPartResult& result) {
- return result.nonfatally_failed();
-}
-
-// Returns true if and only if the test has a non-fatal failure.
-bool TestResult::HasNonfatalFailure() const {
- return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
-}
-
-// Gets the number of all test parts. This is the sum of the number
-// of successful test parts and the number of failed test parts.
-int TestResult::total_part_count() const {
- return static_cast<int>(test_part_results_.size());
-}
-
-// Returns the number of the test properties.
-int TestResult::test_property_count() const {
- return static_cast<int>(test_properties_.size());
-}
-
-// class Test
-
-// Creates a Test object.
-
-// The c'tor saves the states of all flags.
-Test::Test()
- : gtest_flag_saver_(new GTEST_FLAG_SAVER_) {
-}
-
-// The d'tor restores the states of all flags. The actual work is
-// done by the d'tor of the gtest_flag_saver_ field, and thus not
-// visible here.
-Test::~Test() {
-}
-
-// Sets up the test fixture.
-//
-// A sub-class may override this.
-void Test::SetUp() {
-}
-
-// Tears down the test fixture.
-//
-// A sub-class may override this.
-void Test::TearDown() {
-}
-
-// Allows user supplied key value pairs to be recorded for later output.
-void Test::RecordProperty(const std::string& key, const std::string& value) {
- UnitTest::GetInstance()->RecordProperty(key, value);
-}
-
-// Allows user supplied key value pairs to be recorded for later output.
-void Test::RecordProperty(const std::string& key, int value) {
- Message value_message;
- value_message << value;
- RecordProperty(key, value_message.GetString().c_str());
-}
-
-namespace internal {
-
-void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
- const std::string& message) {
- // This function is a friend of UnitTest and as such has access to
- // AddTestPartResult.
- UnitTest::GetInstance()->AddTestPartResult(
- result_type,
- nullptr, // No info about the source file where the exception occurred.
- -1, // We have no info on which line caused the exception.
- message,
- ""); // No stack trace, either.
-}
-
-} // namespace internal
-
-// Google Test requires all tests in the same test suite to use the same test
-// fixture class. This function checks if the current test has the
-// same fixture class as the first test in the current test suite. If
-// yes, it returns true; otherwise it generates a Google Test failure and
-// returns false.
-bool Test::HasSameFixtureClass() {
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- const TestSuite* const test_suite = impl->current_test_suite();
-
- // Info about the first test in the current test suite.
- const TestInfo* const first_test_info = test_suite->test_info_list()[0];
- const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
- const char* const first_test_name = first_test_info->name();
-
- // Info about the current test.
- const TestInfo* const this_test_info = impl->current_test_info();
- const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
- const char* const this_test_name = this_test_info->name();
-
- if (this_fixture_id != first_fixture_id) {
- // Is the first test defined using TEST?
- const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
- // Is this test defined using TEST?
- const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
-
- if (first_is_TEST || this_is_TEST) {
- // Both TEST and TEST_F appear in same test suite, which is incorrect.
- // Tell the user how to fix this.
-
- // Gets the name of the TEST and the name of the TEST_F. Note
- // that first_is_TEST and this_is_TEST cannot both be true, as
- // the fixture IDs are different for the two tests.
- const char* const TEST_name =
- first_is_TEST ? first_test_name : this_test_name;
- const char* const TEST_F_name =
- first_is_TEST ? this_test_name : first_test_name;
-
- ADD_FAILURE()
- << "All tests in the same test suite must use the same test fixture\n"
- << "class, so mixing TEST_F and TEST in the same test suite is\n"
- << "illegal. In test suite " << this_test_info->test_suite_name()
- << ",\n"
- << "test " << TEST_F_name << " is defined using TEST_F but\n"
- << "test " << TEST_name << " is defined using TEST. You probably\n"
- << "want to change the TEST to TEST_F or move it to another test\n"
- << "case.";
- } else {
- // Two fixture classes with the same name appear in two different
- // namespaces, which is not allowed. Tell the user how to fix this.
- ADD_FAILURE()
- << "All tests in the same test suite must use the same test fixture\n"
- << "class. However, in test suite "
- << this_test_info->test_suite_name() << ",\n"
- << "you defined test " << first_test_name << " and test "
- << this_test_name << "\n"
- << "using two different test fixture classes. This can happen if\n"
- << "the two classes are from different namespaces or translation\n"
- << "units and have the same name. You should probably rename one\n"
- << "of the classes to put the tests into different test suites.";
- }
- return false;
- }
-
- return true;
-}
-
-#if GTEST_HAS_SEH
-
-// Adds an "exception thrown" fatal failure to the current test. This
-// function returns its result via an output parameter pointer because VC++
-// prohibits creation of objects with destructors on stack in functions
-// using __try (see error C2712).
-static std::string* FormatSehExceptionMessage(DWORD exception_code,
- const char* location) {
- Message message;
- message << "SEH exception with code 0x" << std::setbase(16) <<
- exception_code << std::setbase(10) << " thrown in " << location << ".";
-
- return new std::string(message.GetString());
-}
-
-#endif // GTEST_HAS_SEH
-
-namespace internal {
-
-#if GTEST_HAS_EXCEPTIONS
-
-// Adds an "exception thrown" fatal failure to the current test.
-static std::string FormatCxxExceptionMessage(const char* description,
- const char* location) {
- Message message;
- if (description != nullptr) {
- message << "C++ exception with description \"" << description << "\"";
- } else {
- message << "Unknown C++ exception";
- }
- message << " thrown in " << location << ".";
-
- return message.GetString();
-}
-
-static std::string PrintTestPartResultToString(
- const TestPartResult& test_part_result);
-
-GoogleTestFailureException::GoogleTestFailureException(
- const TestPartResult& failure)
- : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// We put these helper functions in the internal namespace as IBM's xlC
-// compiler rejects the code if they were declared static.
-
-// Runs the given method and handles SEH exceptions it throws, when
-// SEH is supported; returns the 0-value for type Result in case of an
-// SEH exception. (Microsoft compilers cannot handle SEH and C++
-// exceptions in the same function. Therefore, we provide a separate
-// wrapper function for handling SEH exceptions.)
-template <class T, typename Result>
-Result HandleSehExceptionsInMethodIfSupported(
- T* object, Result (T::*method)(), const char* location) {
-#if GTEST_HAS_SEH
- __try {
- return (object->*method)();
- } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
- GetExceptionCode())) {
- // We create the exception message on the heap because VC++ prohibits
- // creation of objects with destructors on stack in functions using __try
- // (see error C2712).
- std::string* exception_message = FormatSehExceptionMessage(
- GetExceptionCode(), location);
- internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
- *exception_message);
- delete exception_message;
- return static_cast<Result>(0);
- }
-#else
- (void)location;
- return (object->*method)();
-#endif // GTEST_HAS_SEH
-}
-
-// Runs the given method and catches and reports C++ and/or SEH-style
-// exceptions, if they are supported; returns the 0-value for type
-// Result in case of an SEH exception.
-template <class T, typename Result>
-Result HandleExceptionsInMethodIfSupported(
- T* object, Result (T::*method)(), const char* location) {
- // NOTE: The user code can affect the way in which Google Test handles
- // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
- // RUN_ALL_TESTS() starts. It is technically possible to check the flag
- // after the exception is caught and either report or re-throw the
- // exception based on the flag's value:
- //
- // try {
- // // Perform the test method.
- // } catch (...) {
- // if (GTEST_FLAG(catch_exceptions))
- // // Report the exception as failure.
- // else
- // throw; // Re-throws the original exception.
- // }
- //
- // However, the purpose of this flag is to allow the program to drop into
- // the debugger when the exception is thrown. On most platforms, once the
- // control enters the catch block, the exception origin information is
- // lost and the debugger will stop the program at the point of the
- // re-throw in this function -- instead of at the point of the original
- // throw statement in the code under test. For this reason, we perform
- // the check early, sacrificing the ability to affect Google Test's
- // exception handling in the method where the exception is thrown.
- if (internal::GetUnitTestImpl()->catch_exceptions()) {
-#if GTEST_HAS_EXCEPTIONS
- try {
- return HandleSehExceptionsInMethodIfSupported(object, method, location);
- } catch (const AssertionException&) { // NOLINT
- // This failure was reported already.
- } catch (const internal::GoogleTestFailureException&) { // NOLINT
- // This exception type can only be thrown by a failed Google
- // Test assertion with the intention of letting another testing
- // framework catch it. Therefore we just re-throw it.
- throw;
- } catch (const std::exception& e) { // NOLINT
- internal::ReportFailureInUnknownLocation(
- TestPartResult::kFatalFailure,
- FormatCxxExceptionMessage(e.what(), location));
- } catch (...) { // NOLINT
- internal::ReportFailureInUnknownLocation(
- TestPartResult::kFatalFailure,
- FormatCxxExceptionMessage(nullptr, location));
- }
- return static_cast<Result>(0);
-#else
- return HandleSehExceptionsInMethodIfSupported(object, method, location);
-#endif // GTEST_HAS_EXCEPTIONS
- } else {
- return (object->*method)();
- }
-}
-
-} // namespace internal
-
-// Runs the test and updates the test result.
-void Test::Run() {
- if (!HasSameFixtureClass()) return;
-
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->os_stack_trace_getter()->UponLeavingGTest();
- internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
- // We will run the test only if SetUp() was successful and didn't call
- // GTEST_SKIP().
- if (!HasFatalFailure() && !IsSkipped()) {
- impl->os_stack_trace_getter()->UponLeavingGTest();
- internal::HandleExceptionsInMethodIfSupported(
- this, &Test::TestBody, "the test body");
- }
-
- // However, we want to clean up as much as possible. Hence we will
- // always call TearDown(), even if SetUp() or the test body has
- // failed.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- internal::HandleExceptionsInMethodIfSupported(
- this, &Test::TearDown, "TearDown()");
-}
-
-// Returns true if and only if the current test has a fatal failure.
-bool Test::HasFatalFailure() {
- return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
-}
-
-// Returns true if and only if the current test has a non-fatal failure.
-bool Test::HasNonfatalFailure() {
- return internal::GetUnitTestImpl()->current_test_result()->
- HasNonfatalFailure();
-}
-
-// Returns true if and only if the current test was skipped.
-bool Test::IsSkipped() {
- return internal::GetUnitTestImpl()->current_test_result()->Skipped();
-}
-
-// class TestInfo
-
-// Constructs a TestInfo object. It assumes ownership of the test factory
-// object.
-TestInfo::TestInfo(const std::string& a_test_suite_name,
- const std::string& a_name, const char* a_type_param,
- const char* a_value_param,
- internal::CodeLocation a_code_location,
- internal::TypeId fixture_class_id,
- internal::TestFactoryBase* factory)
- : test_suite_name_(a_test_suite_name),
- name_(a_name),
- type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
- value_param_(a_value_param ? new std::string(a_value_param) : nullptr),
- location_(a_code_location),
- fixture_class_id_(fixture_class_id),
- should_run_(false),
- is_disabled_(false),
- matches_filter_(false),
- factory_(factory),
- result_() {}
-
-// Destructs a TestInfo object.
-TestInfo::~TestInfo() { delete factory_; }
-
-namespace internal {
-
-// Creates a new TestInfo object and registers it with Google Test;
-// returns the created object.
-//
-// Arguments:
-//
-// test_suite_name: name of the test suite
-// name: name of the test
-// type_param: the name of the test's type parameter, or NULL if
-// this is not a typed or a type-parameterized test.
-// value_param: text representation of the test's value parameter,
-// or NULL if this is not a value-parameterized test.
-// code_location: code location where the test is defined
-// fixture_class_id: ID of the test fixture class
-// set_up_tc: pointer to the function that sets up the test suite
-// tear_down_tc: pointer to the function that tears down the test suite
-// factory: pointer to the factory that creates a test object.
-// The newly created TestInfo instance will assume
-// ownership of the factory object.
-TestInfo* MakeAndRegisterTestInfo(
- const char* test_suite_name, const char* name, const char* type_param,
- const char* value_param, CodeLocation code_location,
- TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
- TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
- TestInfo* const test_info =
- new TestInfo(test_suite_name, name, type_param, value_param,
- code_location, fixture_class_id, factory);
- GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
- return test_info;
-}
-
-void ReportInvalidTestSuiteType(const char* test_suite_name,
- CodeLocation code_location) {
- Message errors;
- errors
- << "Attempted redefinition of test suite " << test_suite_name << ".\n"
- << "All tests in the same test suite must use the same test fixture\n"
- << "class. However, in test suite " << test_suite_name << ", you tried\n"
- << "to define a test using a fixture class different from the one\n"
- << "used earlier. This can happen if the two fixture classes are\n"
- << "from different namespaces and have the same name. You should\n"
- << "probably rename one of the classes to put the tests into different\n"
- << "test suites.";
-
- GTEST_LOG_(ERROR) << FormatFileLocation(code_location.file.c_str(),
- code_location.line)
- << " " << errors.GetString();
-}
-} // namespace internal
-
-namespace {
-
-// A predicate that checks the test name of a TestInfo against a known
-// value.
-//
-// This is used for implementation of the TestSuite class only. We put
-// it in the anonymous namespace to prevent polluting the outer
-// namespace.
-//
-// TestNameIs is copyable.
-class TestNameIs {
- public:
- // Constructor.
- //
- // TestNameIs has NO default constructor.
- explicit TestNameIs(const char* name)
- : name_(name) {}
-
- // Returns true if and only if the test name of test_info matches name_.
- bool operator()(const TestInfo * test_info) const {
- return test_info && test_info->name() == name_;
- }
-
- private:
- std::string name_;
-};
-
-} // namespace
-
-namespace internal {
-
-// This method expands all parameterized tests registered with macros TEST_P
-// and INSTANTIATE_TEST_SUITE_P into regular tests and registers those.
-// This will be done just once during the program runtime.
-void UnitTestImpl::RegisterParameterizedTests() {
- if (!parameterized_tests_registered_) {
- parameterized_test_registry_.RegisterTests();
- parameterized_tests_registered_ = true;
- }
-}
-
-} // namespace internal
-
-// Creates the test object, runs it, records its result, and then
-// deletes it.
-void TestInfo::Run() {
- if (!should_run_) return;
-
- // Tells UnitTest where to store test result.
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(this);
-
- TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
-
- // Notifies the unit test event listeners that a test is about to start.
- repeater->OnTestStart(*this);
-
- const TimeInMillis start = internal::GetTimeInMillis();
-
- impl->os_stack_trace_getter()->UponLeavingGTest();
-
- // Creates the test object.
- Test* const test = internal::HandleExceptionsInMethodIfSupported(
- factory_, &internal::TestFactoryBase::CreateTest,
- "the test fixture's constructor");
-
- // Runs the test if the constructor didn't generate a fatal failure or invoke
- // GTEST_SKIP().
- // Note that the object will not be null
- if (!Test::HasFatalFailure() && !Test::IsSkipped()) {
- // This doesn't throw as all user code that can throw are wrapped into
- // exception handling code.
- test->Run();
- }
-
- if (test != nullptr) {
- // Deletes the test object.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- internal::HandleExceptionsInMethodIfSupported(
- test, &Test::DeleteSelf_, "the test fixture's destructor");
- }
-
- result_.set_start_timestamp(start);
- result_.set_elapsed_time(internal::GetTimeInMillis() - start);
-
- // Notifies the unit test event listener that a test has just finished.
- repeater->OnTestEnd(*this);
-
- // Tells UnitTest to stop associating assertion results to this
- // test.
- impl->set_current_test_info(nullptr);
-}
-
-// class TestSuite
-
-// Gets the number of successful tests in this test suite.
-int TestSuite::successful_test_count() const {
- return CountIf(test_info_list_, TestPassed);
-}
-
-// Gets the number of successful tests in this test suite.
-int TestSuite::skipped_test_count() const {
- return CountIf(test_info_list_, TestSkipped);
-}
-
-// Gets the number of failed tests in this test suite.
-int TestSuite::failed_test_count() const {
- return CountIf(test_info_list_, TestFailed);
-}
-
-// Gets the number of disabled tests that will be reported in the XML report.
-int TestSuite::reportable_disabled_test_count() const {
- return CountIf(test_info_list_, TestReportableDisabled);
-}
-
-// Gets the number of disabled tests in this test suite.
-int TestSuite::disabled_test_count() const {
- return CountIf(test_info_list_, TestDisabled);
-}
-
-// Gets the number of tests to be printed in the XML report.
-int TestSuite::reportable_test_count() const {
- return CountIf(test_info_list_, TestReportable);
-}
-
-// Get the number of tests in this test suite that should run.
-int TestSuite::test_to_run_count() const {
- return CountIf(test_info_list_, ShouldRunTest);
-}
-
-// Gets the number of all tests.
-int TestSuite::total_test_count() const {
- return static_cast<int>(test_info_list_.size());
-}
-
-// Creates a TestSuite with the given name.
-//
-// Arguments:
-//
-// name: name of the test suite
-// a_type_param: the name of the test suite's type parameter, or NULL if
-// this is not a typed or a type-parameterized test suite.
-// set_up_tc: pointer to the function that sets up the test suite
-// tear_down_tc: pointer to the function that tears down the test suite
-TestSuite::TestSuite(const char* a_name, const char* a_type_param,
- internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc)
- : name_(a_name),
- type_param_(a_type_param ? new std::string(a_type_param) : nullptr),
- set_up_tc_(set_up_tc),
- tear_down_tc_(tear_down_tc),
- should_run_(false),
- start_timestamp_(0),
- elapsed_time_(0) {}
-
-// Destructor of TestSuite.
-TestSuite::~TestSuite() {
- // Deletes every Test in the collection.
- ForEach(test_info_list_, internal::Delete<TestInfo>);
-}
-
-// Returns the i-th test among all the tests. i can range from 0 to
-// total_test_count() - 1. If i is not in that range, returns NULL.
-const TestInfo* TestSuite::GetTestInfo(int i) const {
- const int index = GetElementOr(test_indices_, i, -1);
- return index < 0 ? nullptr : test_info_list_[static_cast<size_t>(index)];
-}
-
-// Returns the i-th test among all the tests. i can range from 0 to
-// total_test_count() - 1. If i is not in that range, returns NULL.
-TestInfo* TestSuite::GetMutableTestInfo(int i) {
- const int index = GetElementOr(test_indices_, i, -1);
- return index < 0 ? nullptr : test_info_list_[static_cast<size_t>(index)];
-}
-
-// Adds a test to this test suite. Will delete the test upon
-// destruction of the TestSuite object.
-void TestSuite::AddTestInfo(TestInfo* test_info) {
- test_info_list_.push_back(test_info);
- test_indices_.push_back(static_cast<int>(test_indices_.size()));
-}
-
-// Runs every test in this TestSuite.
-void TestSuite::Run() {
- if (!should_run_) return;
-
- internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_suite(this);
-
- TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
-
- // Call both legacy and the new API
- repeater->OnTestSuiteStart(*this);
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
- repeater->OnTestCaseStart(*this);
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
-
- impl->os_stack_trace_getter()->UponLeavingGTest();
- internal::HandleExceptionsInMethodIfSupported(
- this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");
-
- start_timestamp_ = internal::GetTimeInMillis();
- for (int i = 0; i < total_test_count(); i++) {
- GetMutableTestInfo(i)->Run();
- }
- elapsed_time_ = internal::GetTimeInMillis() - start_timestamp_;
-
- impl->os_stack_trace_getter()->UponLeavingGTest();
- internal::HandleExceptionsInMethodIfSupported(
- this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");
-
- // Call both legacy and the new API
- repeater->OnTestSuiteEnd(*this);
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
- repeater->OnTestCaseEnd(*this);
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
-
- impl->set_current_test_suite(nullptr);
-}
-
-// Clears the results of all tests in this test suite.
-void TestSuite::ClearResult() {
- ad_hoc_test_result_.Clear();
- ForEach(test_info_list_, TestInfo::ClearTestResult);
-}
-
-// Shuffles the tests in this test suite.
-void TestSuite::ShuffleTests(internal::Random* random) {
- Shuffle(random, &test_indices_);
-}
-
-// Restores the test order to before the first shuffle.
-void TestSuite::UnshuffleTests() {
- for (size_t i = 0; i < test_indices_.size(); i++) {
- test_indices_[i] = static_cast<int>(i);
- }
-}
-
-// Formats a countable noun. Depending on its quantity, either the
-// singular form or the plural form is used. e.g.
-//
-// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
-// FormatCountableNoun(5, "book", "books") returns "5 books".
-static std::string FormatCountableNoun(int count,
- const char * singular_form,
- const char * plural_form) {
- return internal::StreamableToString(count) + " " +
- (count == 1 ? singular_form : plural_form);
-}
-
-// Formats the count of tests.
-static std::string FormatTestCount(int test_count) {
- return FormatCountableNoun(test_count, "test", "tests");
-}
-
-// Formats the count of test suites.
-static std::string FormatTestSuiteCount(int test_suite_count) {
- return FormatCountableNoun(test_suite_count, "test suite", "test suites");
-}
-
-// Converts a TestPartResult::Type enum to human-friendly string
-// representation. Both kNonFatalFailure and kFatalFailure are translated
-// to "Failure", as the user usually doesn't care about the difference
-// between the two when viewing the test result.
-static const char * TestPartResultTypeToString(TestPartResult::Type type) {
- switch (type) {
- case TestPartResult::kSkip:
- return "Skipped";
- case TestPartResult::kSuccess:
- return "Success";
-
- case TestPartResult::kNonFatalFailure:
- case TestPartResult::kFatalFailure:
-#ifdef _MSC_VER
- return "error: ";
-#else
- return "Failure\n";
-#endif
- default:
- return "Unknown result type";
- }
-}
-
-namespace internal {
-
-// Prints a TestPartResult to an std::string.
-static std::string PrintTestPartResultToString(
- const TestPartResult& test_part_result) {
- return (Message()
- << internal::FormatFileLocation(test_part_result.file_name(),
- test_part_result.line_number())
- << " " << TestPartResultTypeToString(test_part_result.type())
- << test_part_result.message()).GetString();
-}
-
-// Prints a TestPartResult.
-static void PrintTestPartResult(const TestPartResult& test_part_result) {
- const std::string& result =
- PrintTestPartResultToString(test_part_result);
- printf("%s\n", result.c_str());
- fflush(stdout);
- // If the test program runs in Visual Studio or a debugger, the
- // following statements add the test part result message to the Output
- // window such that the user can double-click on it to jump to the
- // corresponding source code location; otherwise they do nothing.
-#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
- // We don't call OutputDebugString*() on Windows Mobile, as printing
- // to stdout is done by OutputDebugString() there already - we don't
- // want the same message printed twice.
- ::OutputDebugStringA(result.c_str());
- ::OutputDebugStringA("\n");
-#endif
-}
-
-// class PrettyUnitTestResultPrinter
-#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
- !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW
-
-// Returns the character attribute for the given color.
-static WORD GetColorAttribute(GTestColor color) {
- switch (color) {
- case COLOR_RED: return FOREGROUND_RED;
- case COLOR_GREEN: return FOREGROUND_GREEN;
- case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
- default: return 0;
- }
-}
-
-static int GetBitOffset(WORD color_mask) {
- if (color_mask == 0) return 0;
-
- int bitOffset = 0;
- while ((color_mask & 1) == 0) {
- color_mask >>= 1;
- ++bitOffset;
- }
- return bitOffset;
-}
-
-static WORD GetNewColor(GTestColor color, WORD old_color_attrs) {
- // Let's reuse the BG
- static const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
- BACKGROUND_RED | BACKGROUND_INTENSITY;
- static const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
- FOREGROUND_RED | FOREGROUND_INTENSITY;
- const WORD existing_bg = old_color_attrs & background_mask;
-
- WORD new_color =
- GetColorAttribute(color) | existing_bg | FOREGROUND_INTENSITY;
- static const int bg_bitOffset = GetBitOffset(background_mask);
- static const int fg_bitOffset = GetBitOffset(foreground_mask);
-
- if (((new_color & background_mask) >> bg_bitOffset) ==
- ((new_color & foreground_mask) >> fg_bitOffset)) {
- new_color ^= FOREGROUND_INTENSITY; // invert intensity
- }
- return new_color;
-}
-
-#else
-
-// Returns the ANSI color code for the given color. COLOR_DEFAULT is
-// an invalid input.
-static const char* GetAnsiColorCode(GTestColor color) {
- switch (color) {
- case COLOR_RED: return "1";
- case COLOR_GREEN: return "2";
- case COLOR_YELLOW: return "3";
- default:
- return nullptr;
- }
-}
-
-#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
-
-// Returns true if and only if Google Test should use colors in the output.
-bool ShouldUseColor(bool stdout_is_tty) {
- const char* const gtest_color = GTEST_FLAG(color).c_str();
-
- if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
-#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
- // On Windows the TERM variable is usually not set, but the
- // console there does support colors.
- return stdout_is_tty;
-#else
- // On non-Windows platforms, we rely on the TERM variable.
- const char* const term = posix::GetEnv("TERM");
- const bool term_supports_color =
- String::CStringEquals(term, "xterm") ||
- String::CStringEquals(term, "xterm-color") ||
- String::CStringEquals(term, "xterm-256color") ||
- String::CStringEquals(term, "screen") ||
- String::CStringEquals(term, "screen-256color") ||
- String::CStringEquals(term, "tmux") ||
- String::CStringEquals(term, "tmux-256color") ||
- String::CStringEquals(term, "rxvt-unicode") ||
- String::CStringEquals(term, "rxvt-unicode-256color") ||
- String::CStringEquals(term, "linux") ||
- String::CStringEquals(term, "cygwin");
- return stdout_is_tty && term_supports_color;
-#endif // GTEST_OS_WINDOWS
- }
-
- return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
- String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
- String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
- String::CStringEquals(gtest_color, "1");
- // We take "yes", "true", "t", and "1" as meaning "yes". If the
- // value is neither one of these nor "auto", we treat it as "no" to
- // be conservative.
-}
-
-// Helpers for printing colored strings to stdout. Note that on Windows, we
-// cannot simply emit special characters and have the terminal change colors.
-// This routine must actually emit the characters rather than return a string
-// that would be colored when printed, as can be done on Linux.
-void ColoredPrintf(GTestColor color, const char* fmt, ...) {
- va_list args;
- va_start(args, fmt);
-
-#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS || GTEST_OS_IOS || \
- GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT || defined(ESP_PLATFORM)
- const bool use_color = AlwaysFalse();
-#else
- static const bool in_color_mode =
- ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
- const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
-#endif // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_ZOS
-
- if (!use_color) {
- vprintf(fmt, args);
- va_end(args);
- return;
- }
-
-#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
- !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT && !GTEST_OS_WINDOWS_MINGW
- const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
-
- // Gets the current text color.
- CONSOLE_SCREEN_BUFFER_INFO buffer_info;
- GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
- const WORD old_color_attrs = buffer_info.wAttributes;
- const WORD new_color = GetNewColor(color, old_color_attrs);
-
- // We need to flush the stream buffers into the console before each
- // SetConsoleTextAttribute call lest it affect the text that is already
- // printed but has not yet reached the console.
- fflush(stdout);
- SetConsoleTextAttribute(stdout_handle, new_color);
-
- vprintf(fmt, args);
-
- fflush(stdout);
- // Restores the text color.
- SetConsoleTextAttribute(stdout_handle, old_color_attrs);
-#else
- printf("\033[0;3%sm", GetAnsiColorCode(color));
- vprintf(fmt, args);
- printf("\033[m"); // Resets the terminal to default.
-#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
- va_end(args);
-}
-
-// Text printed in Google Test's text output and --gtest_list_tests
-// output to label the type parameter and value parameter for a test.
-static const char kTypeParamLabel[] = "TypeParam";
-static const char kValueParamLabel[] = "GetParam()";
-
-static void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
- const char* const type_param = test_info.type_param();
- const char* const value_param = test_info.value_param();
-
- if (type_param != nullptr || value_param != nullptr) {
- printf(", where ");
- if (type_param != nullptr) {
- printf("%s = %s", kTypeParamLabel, type_param);
- if (value_param != nullptr) printf(" and ");
- }
- if (value_param != nullptr) {
- printf("%s = %s", kValueParamLabel, value_param);
- }
- }
-}
-
-// This class implements the TestEventListener interface.
-//
-// Class PrettyUnitTestResultPrinter is copyable.
-class PrettyUnitTestResultPrinter : public TestEventListener {
- public:
- PrettyUnitTestResultPrinter() {}
- static void PrintTestName(const char* test_suite, const char* test) {
- printf("%s.%s", test_suite, test);
- }
-
- // The following methods override what's in the TestEventListener class.
- void OnTestProgramStart(const UnitTest& /*unit_test*/) override {}
- void OnTestIterationStart(const UnitTest& unit_test, int iteration) override;
- void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override;
- void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {}
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseStart(const TestCase& test_case) override;
-#else
- void OnTestSuiteStart(const TestSuite& test_suite) override;
-#endif // OnTestCaseStart
-
- void OnTestStart(const TestInfo& test_info) override;
-
- void OnTestPartResult(const TestPartResult& result) override;
- void OnTestEnd(const TestInfo& test_info) override;
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseEnd(const TestCase& test_case) override;
-#else
- void OnTestSuiteEnd(const TestSuite& test_suite) override;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override;
- void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {}
- void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
- void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {}
-
- private:
- static void PrintFailedTests(const UnitTest& unit_test);
- static void PrintSkippedTests(const UnitTest& unit_test);
-};
-
- // Fired before each iteration of tests starts.
-void PrettyUnitTestResultPrinter::OnTestIterationStart(
- const UnitTest& unit_test, int iteration) {
- if (GTEST_FLAG(repeat) != 1)
- printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
-
- const char* const filter = GTEST_FLAG(filter).c_str();
-
- // Prints the filter if it's not *. This reminds the user that some
- // tests may be skipped.
- if (!String::CStringEquals(filter, kUniversalFilter)) {
- ColoredPrintf(COLOR_YELLOW,
- "Note: %s filter = %s\n", GTEST_NAME_, filter);
- }
-
- if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
- const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
- ColoredPrintf(COLOR_YELLOW,
- "Note: This is test shard %d of %s.\n",
- static_cast<int>(shard_index) + 1,
- internal::posix::GetEnv(kTestTotalShards));
- }
-
- if (GTEST_FLAG(shuffle)) {
- ColoredPrintf(COLOR_YELLOW,
- "Note: Randomizing tests' orders with a seed of %d .\n",
- unit_test.random_seed());
- }
-
- ColoredPrintf(COLOR_GREEN, "[==========] ");
- printf("Running %s from %s.\n",
- FormatTestCount(unit_test.test_to_run_count()).c_str(),
- FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
- fflush(stdout);
-}
-
-void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
- const UnitTest& /*unit_test*/) {
- ColoredPrintf(COLOR_GREEN, "[----------] ");
- printf("Global test environment set-up.\n");
- fflush(stdout);
-}
-
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
- const std::string counts =
- FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
- ColoredPrintf(COLOR_GREEN, "[----------] ");
- printf("%s from %s", counts.c_str(), test_case.name());
- if (test_case.type_param() == nullptr) {
- printf("\n");
- } else {
- printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
- }
- fflush(stdout);
-}
-#else
-void PrettyUnitTestResultPrinter::OnTestSuiteStart(
- const TestSuite& test_suite) {
- const std::string counts =
- FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests");
- ColoredPrintf(COLOR_GREEN, "[----------] ");
- printf("%s from %s", counts.c_str(), test_suite.name());
- if (test_suite.type_param() == nullptr) {
- printf("\n");
- } else {
- printf(", where %s = %s\n", kTypeParamLabel, test_suite.type_param());
- }
- fflush(stdout);
-}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
- ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
- PrintTestName(test_info.test_suite_name(), test_info.name());
- printf("\n");
- fflush(stdout);
-}
-
-// Called after an assertion failure.
-void PrettyUnitTestResultPrinter::OnTestPartResult(
- const TestPartResult& result) {
- switch (result.type()) {
- // If the test part succeeded, or was skipped,
- // we don't need to do anything.
- case TestPartResult::kSkip:
- case TestPartResult::kSuccess:
- return;
- default:
- // Print failure message from the assertion
- // (e.g. expected this and got that).
- PrintTestPartResult(result);
- fflush(stdout);
- }
-}
-
-void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
- if (test_info.result()->Passed()) {
- ColoredPrintf(COLOR_GREEN, "[ OK ] ");
- } else if (test_info.result()->Skipped()) {
- ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] ");
- } else {
- ColoredPrintf(COLOR_RED, "[ FAILED ] ");
- }
- PrintTestName(test_info.test_suite_name(), test_info.name());
- if (test_info.result()->Failed())
- PrintFullTestCommentIfPresent(test_info);
-
- if (GTEST_FLAG(print_time)) {
- printf(" (%s ms)\n", internal::StreamableToString(
- test_info.result()->elapsed_time()).c_str());
- } else {
- printf("\n");
- }
- fflush(stdout);
-}
-
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
- if (!GTEST_FLAG(print_time)) return;
-
- const std::string counts =
- FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
- ColoredPrintf(COLOR_GREEN, "[----------] ");
- printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_case.name(),
- internal::StreamableToString(test_case.elapsed_time()).c_str());
- fflush(stdout);
-}
-#else
-void PrettyUnitTestResultPrinter::OnTestSuiteEnd(const TestSuite& test_suite) {
- if (!GTEST_FLAG(print_time)) return;
-
- const std::string counts =
- FormatCountableNoun(test_suite.test_to_run_count(), "test", "tests");
- ColoredPrintf(COLOR_GREEN, "[----------] ");
- printf("%s from %s (%s ms total)\n\n", counts.c_str(), test_suite.name(),
- internal::StreamableToString(test_suite.elapsed_time()).c_str());
- fflush(stdout);
-}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
- const UnitTest& /*unit_test*/) {
- ColoredPrintf(COLOR_GREEN, "[----------] ");
- printf("Global test environment tear-down\n");
- fflush(stdout);
-}
-
-// Internal helper for printing the list of failed tests.
-void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
- const int failed_test_count = unit_test.failed_test_count();
- if (failed_test_count == 0) {
- return;
- }
-
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
- const TestSuite& test_suite = *unit_test.GetTestSuite(i);
- if (!test_suite.should_run() || (test_suite.failed_test_count() == 0)) {
- continue;
- }
- for (int j = 0; j < test_suite.total_test_count(); ++j) {
- const TestInfo& test_info = *test_suite.GetTestInfo(j);
- if (!test_info.should_run() || !test_info.result()->Failed()) {
- continue;
- }
- ColoredPrintf(COLOR_RED, "[ FAILED ] ");
- printf("%s.%s", test_suite.name(), test_info.name());
- PrintFullTestCommentIfPresent(test_info);
- printf("\n");
- }
- }
-}
-
-// Internal helper for printing the list of skipped tests.
-void PrettyUnitTestResultPrinter::PrintSkippedTests(const UnitTest& unit_test) {
- const int skipped_test_count = unit_test.skipped_test_count();
- if (skipped_test_count == 0) {
- return;
- }
-
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
- const TestSuite& test_suite = *unit_test.GetTestSuite(i);
- if (!test_suite.should_run() || (test_suite.skipped_test_count() == 0)) {
- continue;
- }
- for (int j = 0; j < test_suite.total_test_count(); ++j) {
- const TestInfo& test_info = *test_suite.GetTestInfo(j);
- if (!test_info.should_run() || !test_info.result()->Skipped()) {
- continue;
- }
- ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] ");
- printf("%s.%s", test_suite.name(), test_info.name());
- printf("\n");
- }
- }
-}
-
-void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
- int /*iteration*/) {
- ColoredPrintf(COLOR_GREEN, "[==========] ");
- printf("%s from %s ran.",
- FormatTestCount(unit_test.test_to_run_count()).c_str(),
- FormatTestSuiteCount(unit_test.test_suite_to_run_count()).c_str());
- if (GTEST_FLAG(print_time)) {
- printf(" (%s ms total)",
- internal::StreamableToString(unit_test.elapsed_time()).c_str());
- }
- printf("\n");
- ColoredPrintf(COLOR_GREEN, "[ PASSED ] ");
- printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
-
- const int skipped_test_count = unit_test.skipped_test_count();
- if (skipped_test_count > 0) {
- ColoredPrintf(COLOR_GREEN, "[ SKIPPED ] ");
- printf("%s, listed below:\n", FormatTestCount(skipped_test_count).c_str());
- PrintSkippedTests(unit_test);
- }
-
- int num_failures = unit_test.failed_test_count();
- if (!unit_test.Passed()) {
- const int failed_test_count = unit_test.failed_test_count();
- ColoredPrintf(COLOR_RED, "[ FAILED ] ");
- printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
- PrintFailedTests(unit_test);
- printf("\n%2d FAILED %s\n", num_failures,
- num_failures == 1 ? "TEST" : "TESTS");
- }
-
- int num_disabled = unit_test.reportable_disabled_test_count();
- if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
- if (!num_failures) {
- printf("\n"); // Add a spacer if no FAILURE banner is displayed.
- }
- ColoredPrintf(COLOR_YELLOW,
- " YOU HAVE %d DISABLED %s\n\n",
- num_disabled,
- num_disabled == 1 ? "TEST" : "TESTS");
- }
- // Ensure that Google Test output is printed before, e.g., heapchecker output.
- fflush(stdout);
-}
-
-// End PrettyUnitTestResultPrinter
-
-// class TestEventRepeater
-//
-// This class forwards events to other event listeners.
-class TestEventRepeater : public TestEventListener {
- public:
- TestEventRepeater() : forwarding_enabled_(true) {}
- ~TestEventRepeater() override;
- void Append(TestEventListener *listener);
- TestEventListener* Release(TestEventListener* listener);
-
- // Controls whether events will be forwarded to listeners_. Set to false
- // in death test child processes.
- bool forwarding_enabled() const { return forwarding_enabled_; }
- void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
-
- void OnTestProgramStart(const UnitTest& unit_test) override;
- void OnTestIterationStart(const UnitTest& unit_test, int iteration) override;
- void OnEnvironmentsSetUpStart(const UnitTest& unit_test) override;
- void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) override;
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseStart(const TestSuite& parameter) override;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestSuiteStart(const TestSuite& parameter) override;
- void OnTestStart(const TestInfo& test_info) override;
- void OnTestPartResult(const TestPartResult& result) override;
- void OnTestEnd(const TestInfo& test_info) override;
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseEnd(const TestCase& parameter) override;
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestSuiteEnd(const TestSuite& parameter) override;
- void OnEnvironmentsTearDownStart(const UnitTest& unit_test) override;
- void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) override;
- void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
- void OnTestProgramEnd(const UnitTest& unit_test) override;
-
- private:
- // Controls whether events will be forwarded to listeners_. Set to false
- // in death test child processes.
- bool forwarding_enabled_;
- // The list of listeners that receive events.
- std::vector<TestEventListener*> listeners_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
-};
-
-TestEventRepeater::~TestEventRepeater() {
- ForEach(listeners_, Delete<TestEventListener>);
-}
-
-void TestEventRepeater::Append(TestEventListener *listener) {
- listeners_.push_back(listener);
-}
-
-TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
- for (size_t i = 0; i < listeners_.size(); ++i) {
- if (listeners_[i] == listener) {
- listeners_.erase(listeners_.begin() + static_cast<int>(i));
- return listener;
- }
- }
-
- return nullptr;
-}
-
-// Since most methods are very similar, use macros to reduce boilerplate.
-// This defines a member that forwards the call to all listeners.
-#define GTEST_REPEATER_METHOD_(Name, Type) \
-void TestEventRepeater::Name(const Type& parameter) { \
- if (forwarding_enabled_) { \
- for (size_t i = 0; i < listeners_.size(); i++) { \
- listeners_[i]->Name(parameter); \
- } \
- } \
-}
-// This defines a member that forwards the call to all listeners in reverse
-// order.
-#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
- void TestEventRepeater::Name(const Type& parameter) { \
- if (forwarding_enabled_) { \
- for (size_t i = listeners_.size(); i != 0; i--) { \
- listeners_[i - 1]->Name(parameter); \
- } \
- } \
- }
-
-GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
-GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-GTEST_REPEATER_METHOD_(OnTestCaseStart, TestSuite)
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-GTEST_REPEATER_METHOD_(OnTestSuiteStart, TestSuite)
-GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
-GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
-GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
-GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
-GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
-GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestSuite)
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-GTEST_REVERSE_REPEATER_METHOD_(OnTestSuiteEnd, TestSuite)
-GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
-
-#undef GTEST_REPEATER_METHOD_
-#undef GTEST_REVERSE_REPEATER_METHOD_
-
-void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
- int iteration) {
- if (forwarding_enabled_) {
- for (size_t i = 0; i < listeners_.size(); i++) {
- listeners_[i]->OnTestIterationStart(unit_test, iteration);
- }
- }
-}
-
-void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
- int iteration) {
- if (forwarding_enabled_) {
- for (size_t i = listeners_.size(); i > 0; i--) {
- listeners_[i - 1]->OnTestIterationEnd(unit_test, iteration);
- }
- }
-}
-
-// End TestEventRepeater
-
-// This class generates an XML output file.
-class XmlUnitTestResultPrinter : public EmptyTestEventListener {
- public:
- explicit XmlUnitTestResultPrinter(const char* output_file);
-
- void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
- void ListTestsMatchingFilter(const std::vector<TestSuite*>& test_suites);
-
- // Prints an XML summary of all unit tests.
- static void PrintXmlTestsList(std::ostream* stream,
- const std::vector<TestSuite*>& test_suites);
-
- private:
- // Is c a whitespace character that is normalized to a space character
- // when it appears in an XML attribute value?
- static bool IsNormalizableWhitespace(char c) {
- return c == 0x9 || c == 0xA || c == 0xD;
- }
-
- // May c appear in a well-formed XML document?
- static bool IsValidXmlCharacter(char c) {
- return IsNormalizableWhitespace(c) || c >= 0x20;
- }
-
- // Returns an XML-escaped copy of the input string str. If
- // is_attribute is true, the text is meant to appear as an attribute
- // value, and normalizable whitespace is preserved by replacing it
- // with character references.
- static std::string EscapeXml(const std::string& str, bool is_attribute);
-
- // Returns the given string with all characters invalid in XML removed.
- static std::string RemoveInvalidXmlCharacters(const std::string& str);
-
- // Convenience wrapper around EscapeXml when str is an attribute value.
- static std::string EscapeXmlAttribute(const std::string& str) {
- return EscapeXml(str, true);
- }
-
- // Convenience wrapper around EscapeXml when str is not an attribute value.
- static std::string EscapeXmlText(const char* str) {
- return EscapeXml(str, false);
- }
-
- // Verifies that the given attribute belongs to the given element and
- // streams the attribute as XML.
- static void OutputXmlAttribute(std::ostream* stream,
- const std::string& element_name,
- const std::string& name,
- const std::string& value);
-
- // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
- static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
-
- // Streams an XML representation of a TestInfo object.
- static void OutputXmlTestInfo(::std::ostream* stream,
- const char* test_suite_name,
- const TestInfo& test_info);
-
- // Prints an XML representation of a TestSuite object
- static void PrintXmlTestSuite(::std::ostream* stream,
- const TestSuite& test_suite);
-
- // Prints an XML summary of unit_test to output stream out.
- static void PrintXmlUnitTest(::std::ostream* stream,
- const UnitTest& unit_test);
-
- // Produces a string representing the test properties in a result as space
- // delimited XML attributes based on the property key="value" pairs.
- // When the std::string is not empty, it includes a space at the beginning,
- // to delimit this attribute from prior attributes.
- static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
-
- // Streams an XML representation of the test properties of a TestResult
- // object.
- static void OutputXmlTestProperties(std::ostream* stream,
- const TestResult& result);
-
- // The output file.
- const std::string output_file_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
-};
-
-// Creates a new XmlUnitTestResultPrinter.
-XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
- : output_file_(output_file) {
- if (output_file_.empty()) {
- GTEST_LOG_(FATAL) << "XML output file may not be null";
- }
-}
-
-// Called after the unit test ends.
-void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
- int /*iteration*/) {
- FILE* xmlout = OpenFileForWriting(output_file_);
- std::stringstream stream;
- PrintXmlUnitTest(&stream, unit_test);
- fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
- fclose(xmlout);
-}
-
-void XmlUnitTestResultPrinter::ListTestsMatchingFilter(
- const std::vector<TestSuite*>& test_suites) {
- FILE* xmlout = OpenFileForWriting(output_file_);
- std::stringstream stream;
- PrintXmlTestsList(&stream, test_suites);
- fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
- fclose(xmlout);
-}
-
-// Returns an XML-escaped copy of the input string str. If is_attribute
-// is true, the text is meant to appear as an attribute value, and
-// normalizable whitespace is preserved by replacing it with character
-// references.
-//
-// Invalid XML characters in str, if any, are stripped from the output.
-// It is expected that most, if not all, of the text processed by this
-// module will consist of ordinary English text.
-// If this module is ever modified to produce version 1.1 XML output,
-// most invalid characters can be retained using character references.
-std::string XmlUnitTestResultPrinter::EscapeXml(
- const std::string& str, bool is_attribute) {
- Message m;
-
- for (size_t i = 0; i < str.size(); ++i) {
- const char ch = str[i];
- switch (ch) {
- case '<':
- m << "<";
- break;
- case '>':
- m << ">";
- break;
- case '&':
- m << "&";
- break;
- case '\'':
- if (is_attribute)
- m << "'";
- else
- m << '\'';
- break;
- case '"':
- if (is_attribute)
- m << """;
- else
- m << '"';
- break;
- default:
- if (IsValidXmlCharacter(ch)) {
- if (is_attribute && IsNormalizableWhitespace(ch))
- m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
- << ";";
- else
- m << ch;
- }
- break;
- }
- }
-
- return m.GetString();
-}
-
-// Returns the given string with all characters invalid in XML removed.
-// Currently invalid characters are dropped from the string. An
-// alternative is to replace them with certain characters such as . or ?.
-std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
- const std::string& str) {
- std::string output;
- output.reserve(str.size());
- for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
- if (IsValidXmlCharacter(*it))
- output.push_back(*it);
-
- return output;
-}
-
-// The following routines generate an XML representation of a UnitTest
-// object.
-// GOOGLETEST_CM0009 DO NOT DELETE
-//
-// This is how Google Test concepts map to the DTD:
-//
-// <testsuites name="AllTests"> <-- corresponds to a UnitTest object
-// <testsuite name="testcase-name"> <-- corresponds to a TestSuite object
-// <testcase name="test-name"> <-- corresponds to a TestInfo object
-// <failure message="...">...</failure>
-// <failure message="...">...</failure>
-// <failure message="...">...</failure>
-// <-- individual assertion failures
-// </testcase>
-// </testsuite>
-// </testsuites>
-
-// Formats the given time in milliseconds as seconds.
-std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
- ::std::stringstream ss;
- ss << (static_cast<double>(ms) * 1e-3);
- return ss.str();
-}
-
-static bool PortableLocaltime(time_t seconds, struct tm* out) {
-#if defined(_MSC_VER)
- return localtime_s(out, &seconds) == 0;
-#elif defined(__MINGW32__) || defined(__MINGW64__)
- // MINGW <time.h> provides neither localtime_r nor localtime_s, but uses
- // Windows' localtime(), which has a thread-local tm buffer.
- struct tm* tm_ptr = localtime(&seconds); // NOLINT
- if (tm_ptr == nullptr) return false;
- *out = *tm_ptr;
- return true;
-#else
- return localtime_r(&seconds, out) != nullptr;
-#endif
-}
-
-// Converts the given epoch time in milliseconds to a date string in the ISO
-// 8601 format, without the timezone information.
-std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
- struct tm time_struct;
- if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
- return "";
- // YYYY-MM-DDThh:mm:ss
- return StreamableToString(time_struct.tm_year + 1900) + "-" +
- String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
- String::FormatIntWidth2(time_struct.tm_mday) + "T" +
- String::FormatIntWidth2(time_struct.tm_hour) + ":" +
- String::FormatIntWidth2(time_struct.tm_min) + ":" +
- String::FormatIntWidth2(time_struct.tm_sec);
-}
-
-// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
-void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
- const char* data) {
- const char* segment = data;
- *stream << "<![CDATA[";
- for (;;) {
- const char* const next_segment = strstr(segment, "]]>");
- if (next_segment != nullptr) {
- stream->write(
- segment, static_cast<std::streamsize>(next_segment - segment));
- *stream << "]]>]]><![CDATA[";
- segment = next_segment + strlen("]]>");
- } else {
- *stream << segment;
- break;
- }
- }
- *stream << "]]>";
-}
-
-void XmlUnitTestResultPrinter::OutputXmlAttribute(
- std::ostream* stream,
- const std::string& element_name,
- const std::string& name,
- const std::string& value) {
- const std::vector<std::string>& allowed_names =
- GetReservedOutputAttributesForElement(element_name);
-
- GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
- allowed_names.end())
- << "Attribute " << name << " is not allowed for element <" << element_name
- << ">.";
-
- *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
-}
-
-// Prints an XML representation of a TestInfo object.
-void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
- const char* test_suite_name,
- const TestInfo& test_info) {
- const TestResult& result = *test_info.result();
- const std::string kTestsuite = "testcase";
-
- if (test_info.is_in_another_shard()) {
- return;
- }
-
- *stream << " <testcase";
- OutputXmlAttribute(stream, kTestsuite, "name", test_info.name());
-
- if (test_info.value_param() != nullptr) {
- OutputXmlAttribute(stream, kTestsuite, "value_param",
- test_info.value_param());
- }
- if (test_info.type_param() != nullptr) {
- OutputXmlAttribute(stream, kTestsuite, "type_param",
- test_info.type_param());
- }
- if (GTEST_FLAG(list_tests)) {
- OutputXmlAttribute(stream, kTestsuite, "file", test_info.file());
- OutputXmlAttribute(stream, kTestsuite, "line",
- StreamableToString(test_info.line()));
- *stream << " />\n";
- return;
- }
-
- OutputXmlAttribute(stream, kTestsuite, "status",
- test_info.should_run() ? "run" : "notrun");
- OutputXmlAttribute(stream, kTestsuite, "result",
- test_info.should_run()
- ? (result.Skipped() ? "skipped" : "completed")
- : "suppressed");
- OutputXmlAttribute(stream, kTestsuite, "time",
- FormatTimeInMillisAsSeconds(result.elapsed_time()));
- OutputXmlAttribute(
- stream, kTestsuite, "timestamp",
- FormatEpochTimeInMillisAsIso8601(result.start_timestamp()));
- OutputXmlAttribute(stream, kTestsuite, "classname", test_suite_name);
-
- int failures = 0;
- for (int i = 0; i < result.total_part_count(); ++i) {
- const TestPartResult& part = result.GetTestPartResult(i);
- if (part.failed()) {
- if (++failures == 1) {
- *stream << ">\n";
- }
- const std::string location =
- internal::FormatCompilerIndependentFileLocation(part.file_name(),
- part.line_number());
- const std::string summary = location + "\n" + part.summary();
- *stream << " <failure message=\""
- << EscapeXmlAttribute(summary.c_str())
- << "\" type=\"\">";
- const std::string detail = location + "\n" + part.message();
- OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
- *stream << "</failure>\n";
- }
- }
-
- if (failures == 0 && result.test_property_count() == 0) {
- *stream << " />\n";
- } else {
- if (failures == 0) {
- *stream << ">\n";
- }
- OutputXmlTestProperties(stream, result);
- *stream << " </testcase>\n";
- }
-}
-
-// Prints an XML representation of a TestSuite object
-void XmlUnitTestResultPrinter::PrintXmlTestSuite(std::ostream* stream,
- const TestSuite& test_suite) {
- const std::string kTestsuite = "testsuite";
- *stream << " <" << kTestsuite;
- OutputXmlAttribute(stream, kTestsuite, "name", test_suite.name());
- OutputXmlAttribute(stream, kTestsuite, "tests",
- StreamableToString(test_suite.reportable_test_count()));
- if (!GTEST_FLAG(list_tests)) {
- OutputXmlAttribute(stream, kTestsuite, "failures",
- StreamableToString(test_suite.failed_test_count()));
- OutputXmlAttribute(
- stream, kTestsuite, "disabled",
- StreamableToString(test_suite.reportable_disabled_test_count()));
- OutputXmlAttribute(stream, kTestsuite, "errors", "0");
- OutputXmlAttribute(stream, kTestsuite, "time",
- FormatTimeInMillisAsSeconds(test_suite.elapsed_time()));
- OutputXmlAttribute(
- stream, kTestsuite, "timestamp",
- FormatEpochTimeInMillisAsIso8601(test_suite.start_timestamp()));
- *stream << TestPropertiesAsXmlAttributes(test_suite.ad_hoc_test_result());
- }
- *stream << ">\n";
- for (int i = 0; i < test_suite.total_test_count(); ++i) {
- if (test_suite.GetTestInfo(i)->is_reportable())
- OutputXmlTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
- }
- *stream << " </" << kTestsuite << ">\n";
-}
-
-// Prints an XML summary of unit_test to output stream out.
-void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
- const UnitTest& unit_test) {
- const std::string kTestsuites = "testsuites";
-
- *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
- *stream << "<" << kTestsuites;
-
- OutputXmlAttribute(stream, kTestsuites, "tests",
- StreamableToString(unit_test.reportable_test_count()));
- OutputXmlAttribute(stream, kTestsuites, "failures",
- StreamableToString(unit_test.failed_test_count()));
- OutputXmlAttribute(
- stream, kTestsuites, "disabled",
- StreamableToString(unit_test.reportable_disabled_test_count()));
- OutputXmlAttribute(stream, kTestsuites, "errors", "0");
- OutputXmlAttribute(stream, kTestsuites, "time",
- FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
- OutputXmlAttribute(
- stream, kTestsuites, "timestamp",
- FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
-
- if (GTEST_FLAG(shuffle)) {
- OutputXmlAttribute(stream, kTestsuites, "random_seed",
- StreamableToString(unit_test.random_seed()));
- }
- *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
-
- OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
- *stream << ">\n";
-
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
- if (unit_test.GetTestSuite(i)->reportable_test_count() > 0)
- PrintXmlTestSuite(stream, *unit_test.GetTestSuite(i));
- }
- *stream << "</" << kTestsuites << ">\n";
-}
-
-void XmlUnitTestResultPrinter::PrintXmlTestsList(
- std::ostream* stream, const std::vector<TestSuite*>& test_suites) {
- const std::string kTestsuites = "testsuites";
-
- *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
- *stream << "<" << kTestsuites;
-
- int total_tests = 0;
- for (auto test_suite : test_suites) {
- total_tests += test_suite->total_test_count();
- }
- OutputXmlAttribute(stream, kTestsuites, "tests",
- StreamableToString(total_tests));
- OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
- *stream << ">\n";
-
- for (auto test_suite : test_suites) {
- PrintXmlTestSuite(stream, *test_suite);
- }
- *stream << "</" << kTestsuites << ">\n";
-}
-
-// Produces a string representing the test properties in a result as space
-// delimited XML attributes based on the property key="value" pairs.
-std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
- const TestResult& result) {
- Message attributes;
- for (int i = 0; i < result.test_property_count(); ++i) {
- const TestProperty& property = result.GetTestProperty(i);
- attributes << " " << property.key() << "="
- << "\"" << EscapeXmlAttribute(property.value()) << "\"";
- }
- return attributes.GetString();
-}
-
-void XmlUnitTestResultPrinter::OutputXmlTestProperties(
- std::ostream* stream, const TestResult& result) {
- const std::string kProperties = "properties";
- const std::string kProperty = "property";
-
- if (result.test_property_count() <= 0) {
- return;
- }
-
- *stream << "<" << kProperties << ">\n";
- for (int i = 0; i < result.test_property_count(); ++i) {
- const TestProperty& property = result.GetTestProperty(i);
- *stream << "<" << kProperty;
- *stream << " name=\"" << EscapeXmlAttribute(property.key()) << "\"";
- *stream << " value=\"" << EscapeXmlAttribute(property.value()) << "\"";
- *stream << "/>\n";
- }
- *stream << "</" << kProperties << ">\n";
-}
-
-// End XmlUnitTestResultPrinter
-
-// This class generates an JSON output file.
-class JsonUnitTestResultPrinter : public EmptyTestEventListener {
- public:
- explicit JsonUnitTestResultPrinter(const char* output_file);
-
- void OnTestIterationEnd(const UnitTest& unit_test, int iteration) override;
-
- // Prints an JSON summary of all unit tests.
- static void PrintJsonTestList(::std::ostream* stream,
- const std::vector<TestSuite*>& test_suites);
-
- private:
- // Returns an JSON-escaped copy of the input string str.
- static std::string EscapeJson(const std::string& str);
-
- //// Verifies that the given attribute belongs to the given element and
- //// streams the attribute as JSON.
- static void OutputJsonKey(std::ostream* stream,
- const std::string& element_name,
- const std::string& name,
- const std::string& value,
- const std::string& indent,
- bool comma = true);
- static void OutputJsonKey(std::ostream* stream,
- const std::string& element_name,
- const std::string& name,
- int value,
- const std::string& indent,
- bool comma = true);
-
- // Streams a JSON representation of a TestInfo object.
- static void OutputJsonTestInfo(::std::ostream* stream,
- const char* test_suite_name,
- const TestInfo& test_info);
-
- // Prints a JSON representation of a TestSuite object
- static void PrintJsonTestSuite(::std::ostream* stream,
- const TestSuite& test_suite);
-
- // Prints a JSON summary of unit_test to output stream out.
- static void PrintJsonUnitTest(::std::ostream* stream,
- const UnitTest& unit_test);
-
- // Produces a string representing the test properties in a result as
- // a JSON dictionary.
- static std::string TestPropertiesAsJson(const TestResult& result,
- const std::string& indent);
-
- // The output file.
- const std::string output_file_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(JsonUnitTestResultPrinter);
-};
-
-// Creates a new JsonUnitTestResultPrinter.
-JsonUnitTestResultPrinter::JsonUnitTestResultPrinter(const char* output_file)
- : output_file_(output_file) {
- if (output_file_.empty()) {
- GTEST_LOG_(FATAL) << "JSON output file may not be null";
- }
-}
-
-void JsonUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
- int /*iteration*/) {
- FILE* jsonout = OpenFileForWriting(output_file_);
- std::stringstream stream;
- PrintJsonUnitTest(&stream, unit_test);
- fprintf(jsonout, "%s", StringStreamToString(&stream).c_str());
- fclose(jsonout);
-}
-
-// Returns an JSON-escaped copy of the input string str.
-std::string JsonUnitTestResultPrinter::EscapeJson(const std::string& str) {
- Message m;
-
- for (size_t i = 0; i < str.size(); ++i) {
- const char ch = str[i];
- switch (ch) {
- case '\\':
- case '"':
- case '/':
- m << '\\' << ch;
- break;
- case '\b':
- m << "\\b";
- break;
- case '\t':
- m << "\\t";
- break;
- case '\n':
- m << "\\n";
- break;
- case '\f':
- m << "\\f";
- break;
- case '\r':
- m << "\\r";
- break;
- default:
- if (ch < ' ') {
- m << "\\u00" << String::FormatByte(static_cast<unsigned char>(ch));
- } else {
- m << ch;
- }
- break;
- }
- }
-
- return m.GetString();
-}
-
-// The following routines generate an JSON representation of a UnitTest
-// object.
-
-// Formats the given time in milliseconds as seconds.
-static std::string FormatTimeInMillisAsDuration(TimeInMillis ms) {
- ::std::stringstream ss;
- ss << (static_cast<double>(ms) * 1e-3) << "s";
- return ss.str();
-}
-
-// Converts the given epoch time in milliseconds to a date string in the
-// RFC3339 format, without the timezone information.
-static std::string FormatEpochTimeInMillisAsRFC3339(TimeInMillis ms) {
- struct tm time_struct;
- if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
- return "";
- // YYYY-MM-DDThh:mm:ss
- return StreamableToString(time_struct.tm_year + 1900) + "-" +
- String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
- String::FormatIntWidth2(time_struct.tm_mday) + "T" +
- String::FormatIntWidth2(time_struct.tm_hour) + ":" +
- String::FormatIntWidth2(time_struct.tm_min) + ":" +
- String::FormatIntWidth2(time_struct.tm_sec) + "Z";
-}
-
-static inline std::string Indent(size_t width) {
- return std::string(width, ' ');
-}
-
-void JsonUnitTestResultPrinter::OutputJsonKey(
- std::ostream* stream,
- const std::string& element_name,
- const std::string& name,
- const std::string& value,
- const std::string& indent,
- bool comma) {
- const std::vector<std::string>& allowed_names =
- GetReservedOutputAttributesForElement(element_name);
-
- GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
- allowed_names.end())
- << "Key \"" << name << "\" is not allowed for value \"" << element_name
- << "\".";
-
- *stream << indent << "\"" << name << "\": \"" << EscapeJson(value) << "\"";
- if (comma)
- *stream << ",\n";
-}
-
-void JsonUnitTestResultPrinter::OutputJsonKey(
- std::ostream* stream,
- const std::string& element_name,
- const std::string& name,
- int value,
- const std::string& indent,
- bool comma) {
- const std::vector<std::string>& allowed_names =
- GetReservedOutputAttributesForElement(element_name);
-
- GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
- allowed_names.end())
- << "Key \"" << name << "\" is not allowed for value \"" << element_name
- << "\".";
-
- *stream << indent << "\"" << name << "\": " << StreamableToString(value);
- if (comma)
- *stream << ",\n";
-}
-
-// Prints a JSON representation of a TestInfo object.
-void JsonUnitTestResultPrinter::OutputJsonTestInfo(::std::ostream* stream,
- const char* test_suite_name,
- const TestInfo& test_info) {
- const TestResult& result = *test_info.result();
- const std::string kTestsuite = "testcase";
- const std::string kIndent = Indent(10);
-
- *stream << Indent(8) << "{\n";
- OutputJsonKey(stream, kTestsuite, "name", test_info.name(), kIndent);
-
- if (test_info.value_param() != nullptr) {
- OutputJsonKey(stream, kTestsuite, "value_param", test_info.value_param(),
- kIndent);
- }
- if (test_info.type_param() != nullptr) {
- OutputJsonKey(stream, kTestsuite, "type_param", test_info.type_param(),
- kIndent);
- }
- if (GTEST_FLAG(list_tests)) {
- OutputJsonKey(stream, kTestsuite, "file", test_info.file(), kIndent);
- OutputJsonKey(stream, kTestsuite, "line", test_info.line(), kIndent, false);
- *stream << "\n" << Indent(8) << "}";
- return;
- }
-
- OutputJsonKey(stream, kTestsuite, "status",
- test_info.should_run() ? "RUN" : "NOTRUN", kIndent);
- OutputJsonKey(stream, kTestsuite, "result",
- test_info.should_run()
- ? (result.Skipped() ? "SKIPPED" : "COMPLETED")
- : "SUPPRESSED",
- kIndent);
- OutputJsonKey(stream, kTestsuite, "timestamp",
- FormatEpochTimeInMillisAsRFC3339(result.start_timestamp()),
- kIndent);
- OutputJsonKey(stream, kTestsuite, "time",
- FormatTimeInMillisAsDuration(result.elapsed_time()), kIndent);
- OutputJsonKey(stream, kTestsuite, "classname", test_suite_name, kIndent,
- false);
- *stream << TestPropertiesAsJson(result, kIndent);
-
- int failures = 0;
- for (int i = 0; i < result.total_part_count(); ++i) {
- const TestPartResult& part = result.GetTestPartResult(i);
- if (part.failed()) {
- *stream << ",\n";
- if (++failures == 1) {
- *stream << kIndent << "\"" << "failures" << "\": [\n";
- }
- const std::string location =
- internal::FormatCompilerIndependentFileLocation(part.file_name(),
- part.line_number());
- const std::string message = EscapeJson(location + "\n" + part.message());
- *stream << kIndent << " {\n"
- << kIndent << " \"failure\": \"" << message << "\",\n"
- << kIndent << " \"type\": \"\"\n"
- << kIndent << " }";
- }
- }
-
- if (failures > 0)
- *stream << "\n" << kIndent << "]";
- *stream << "\n" << Indent(8) << "}";
-}
-
-// Prints an JSON representation of a TestSuite object
-void JsonUnitTestResultPrinter::PrintJsonTestSuite(
- std::ostream* stream, const TestSuite& test_suite) {
- const std::string kTestsuite = "testsuite";
- const std::string kIndent = Indent(6);
-
- *stream << Indent(4) << "{\n";
- OutputJsonKey(stream, kTestsuite, "name", test_suite.name(), kIndent);
- OutputJsonKey(stream, kTestsuite, "tests", test_suite.reportable_test_count(),
- kIndent);
- if (!GTEST_FLAG(list_tests)) {
- OutputJsonKey(stream, kTestsuite, "failures",
- test_suite.failed_test_count(), kIndent);
- OutputJsonKey(stream, kTestsuite, "disabled",
- test_suite.reportable_disabled_test_count(), kIndent);
- OutputJsonKey(stream, kTestsuite, "errors", 0, kIndent);
- OutputJsonKey(
- stream, kTestsuite, "timestamp",
- FormatEpochTimeInMillisAsRFC3339(test_suite.start_timestamp()),
- kIndent);
- OutputJsonKey(stream, kTestsuite, "time",
- FormatTimeInMillisAsDuration(test_suite.elapsed_time()),
- kIndent, false);
- *stream << TestPropertiesAsJson(test_suite.ad_hoc_test_result(), kIndent)
- << ",\n";
- }
-
- *stream << kIndent << "\"" << kTestsuite << "\": [\n";
-
- bool comma = false;
- for (int i = 0; i < test_suite.total_test_count(); ++i) {
- if (test_suite.GetTestInfo(i)->is_reportable()) {
- if (comma) {
- *stream << ",\n";
- } else {
- comma = true;
- }
- OutputJsonTestInfo(stream, test_suite.name(), *test_suite.GetTestInfo(i));
- }
- }
- *stream << "\n" << kIndent << "]\n" << Indent(4) << "}";
-}
-
-// Prints a JSON summary of unit_test to output stream out.
-void JsonUnitTestResultPrinter::PrintJsonUnitTest(std::ostream* stream,
- const UnitTest& unit_test) {
- const std::string kTestsuites = "testsuites";
- const std::string kIndent = Indent(2);
- *stream << "{\n";
-
- OutputJsonKey(stream, kTestsuites, "tests", unit_test.reportable_test_count(),
- kIndent);
- OutputJsonKey(stream, kTestsuites, "failures", unit_test.failed_test_count(),
- kIndent);
- OutputJsonKey(stream, kTestsuites, "disabled",
- unit_test.reportable_disabled_test_count(), kIndent);
- OutputJsonKey(stream, kTestsuites, "errors", 0, kIndent);
- if (GTEST_FLAG(shuffle)) {
- OutputJsonKey(stream, kTestsuites, "random_seed", unit_test.random_seed(),
- kIndent);
- }
- OutputJsonKey(stream, kTestsuites, "timestamp",
- FormatEpochTimeInMillisAsRFC3339(unit_test.start_timestamp()),
- kIndent);
- OutputJsonKey(stream, kTestsuites, "time",
- FormatTimeInMillisAsDuration(unit_test.elapsed_time()), kIndent,
- false);
-
- *stream << TestPropertiesAsJson(unit_test.ad_hoc_test_result(), kIndent)
- << ",\n";
-
- OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
- *stream << kIndent << "\"" << kTestsuites << "\": [\n";
-
- bool comma = false;
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
- if (unit_test.GetTestSuite(i)->reportable_test_count() > 0) {
- if (comma) {
- *stream << ",\n";
- } else {
- comma = true;
- }
- PrintJsonTestSuite(stream, *unit_test.GetTestSuite(i));
- }
- }
-
- *stream << "\n" << kIndent << "]\n" << "}\n";
-}
-
-void JsonUnitTestResultPrinter::PrintJsonTestList(
- std::ostream* stream, const std::vector<TestSuite*>& test_suites) {
- const std::string kTestsuites = "testsuites";
- const std::string kIndent = Indent(2);
- *stream << "{\n";
- int total_tests = 0;
- for (auto test_suite : test_suites) {
- total_tests += test_suite->total_test_count();
- }
- OutputJsonKey(stream, kTestsuites, "tests", total_tests, kIndent);
-
- OutputJsonKey(stream, kTestsuites, "name", "AllTests", kIndent);
- *stream << kIndent << "\"" << kTestsuites << "\": [\n";
-
- for (size_t i = 0; i < test_suites.size(); ++i) {
- if (i != 0) {
- *stream << ",\n";
- }
- PrintJsonTestSuite(stream, *test_suites[i]);
- }
-
- *stream << "\n"
- << kIndent << "]\n"
- << "}\n";
-}
-// Produces a string representing the test properties in a result as
-// a JSON dictionary.
-std::string JsonUnitTestResultPrinter::TestPropertiesAsJson(
- const TestResult& result, const std::string& indent) {
- Message attributes;
- for (int i = 0; i < result.test_property_count(); ++i) {
- const TestProperty& property = result.GetTestProperty(i);
- attributes << ",\n" << indent << "\"" << property.key() << "\": "
- << "\"" << EscapeJson(property.value()) << "\"";
- }
- return attributes.GetString();
-}
-
-// End JsonUnitTestResultPrinter
-
-#if GTEST_CAN_STREAM_RESULTS_
-
-// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
-// replaces them by "%xx" where xx is their hexadecimal value. For
-// example, replaces "=" with "%3D". This algorithm is O(strlen(str))
-// in both time and space -- important as the input str may contain an
-// arbitrarily long test failure message and stack trace.
-std::string StreamingListener::UrlEncode(const char* str) {
- std::string result;
- result.reserve(strlen(str) + 1);
- for (char ch = *str; ch != '\0'; ch = *++str) {
- switch (ch) {
- case '%':
- case '=':
- case '&':
- case '\n':
- result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
- break;
- default:
- result.push_back(ch);
- break;
- }
- }
- return result;
-}
-
-void StreamingListener::SocketWriter::MakeConnection() {
- GTEST_CHECK_(sockfd_ == -1)
- << "MakeConnection() can't be called when there is already a connection.";
-
- addrinfo hints;
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses.
- hints.ai_socktype = SOCK_STREAM;
- addrinfo* servinfo = nullptr;
-
- // Use the getaddrinfo() to get a linked list of IP addresses for
- // the given host name.
- const int error_num = getaddrinfo(
- host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
- if (error_num != 0) {
- GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
- << gai_strerror(error_num);
- }
-
- // Loop through all the results and connect to the first we can.
- for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != nullptr;
- cur_addr = cur_addr->ai_next) {
- sockfd_ = socket(
- cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
- if (sockfd_ != -1) {
- // Connect the client socket to the server socket.
- if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
- close(sockfd_);
- sockfd_ = -1;
- }
- }
- }
-
- freeaddrinfo(servinfo); // all done with this structure
-
- if (sockfd_ == -1) {
- GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
- << host_name_ << ":" << port_num_;
- }
-}
-
-// End of class Streaming Listener
-#endif // GTEST_CAN_STREAM_RESULTS__
-
-// class OsStackTraceGetter
-
-const char* const OsStackTraceGetterInterface::kElidedFramesMarker =
- "... " GTEST_NAME_ " internal frames ...";
-
-std::string OsStackTraceGetter::CurrentStackTrace(int max_depth, int skip_count)
- GTEST_LOCK_EXCLUDED_(mutex_) {
-#if GTEST_HAS_ABSL
- std::string result;
-
- if (max_depth <= 0) {
- return result;
- }
-
- max_depth = std::min(max_depth, kMaxStackTraceDepth);
-
- std::vector<void*> raw_stack(max_depth);
- // Skips the frames requested by the caller, plus this function.
- const int raw_stack_size =
- absl::GetStackTrace(&raw_stack[0], max_depth, skip_count + 1);
-
- void* caller_frame = nullptr;
- {
- MutexLock lock(&mutex_);
- caller_frame = caller_frame_;
- }
-
- for (int i = 0; i < raw_stack_size; ++i) {
- if (raw_stack[i] == caller_frame &&
- !GTEST_FLAG(show_internal_stack_frames)) {
- // Add a marker to the trace and stop adding frames.
- absl::StrAppend(&result, kElidedFramesMarker, "\n");
- break;
- }
-
- char tmp[1024];
- const char* symbol = "(unknown)";
- if (absl::Symbolize(raw_stack[i], tmp, sizeof(tmp))) {
- symbol = tmp;
- }
-
- char line[1024];
- snprintf(line, sizeof(line), " %p: %s\n", raw_stack[i], symbol);
- result += line;
- }
-
- return result;
-
-#else // !GTEST_HAS_ABSL
- static_cast<void>(max_depth);
- static_cast<void>(skip_count);
- return "";
-#endif // GTEST_HAS_ABSL
-}
-
-void OsStackTraceGetter::UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_) {
-#if GTEST_HAS_ABSL
- void* caller_frame = nullptr;
- if (absl::GetStackTrace(&caller_frame, 1, 3) <= 0) {
- caller_frame = nullptr;
- }
-
- MutexLock lock(&mutex_);
- caller_frame_ = caller_frame;
-#endif // GTEST_HAS_ABSL
-}
-
-// A helper class that creates the premature-exit file in its
-// constructor and deletes the file in its destructor.
-class ScopedPrematureExitFile {
- public:
- explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
- : premature_exit_filepath_(premature_exit_filepath ?
- premature_exit_filepath : "") {
- // If a path to the premature-exit file is specified...
- if (!premature_exit_filepath_.empty()) {
- // create the file with a single "0" character in it. I/O
- // errors are ignored as there's nothing better we can do and we
- // don't want to fail the test because of this.
- FILE* pfile = posix::FOpen(premature_exit_filepath, "w");
- fwrite("0", 1, 1, pfile);
- fclose(pfile);
- }
- }
-
- ~ScopedPrematureExitFile() {
- if (!premature_exit_filepath_.empty()) {
- int retval = remove(premature_exit_filepath_.c_str());
- if (retval) {
- GTEST_LOG_(ERROR) << "Failed to remove premature exit filepath \""
- << premature_exit_filepath_ << "\" with error "
- << retval;
- }
- }
- }
-
- private:
- const std::string premature_exit_filepath_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
-};
-
-} // namespace internal
-
-// class TestEventListeners
-
-TestEventListeners::TestEventListeners()
- : repeater_(new internal::TestEventRepeater()),
- default_result_printer_(nullptr),
- default_xml_generator_(nullptr) {}
-
-TestEventListeners::~TestEventListeners() { delete repeater_; }
-
-// Returns the standard listener responsible for the default console
-// output. Can be removed from the listeners list to shut down default
-// console output. Note that removing this object from the listener list
-// with Release transfers its ownership to the user.
-void TestEventListeners::Append(TestEventListener* listener) {
- repeater_->Append(listener);
-}
-
-// Removes the given event listener from the list and returns it. It then
-// becomes the caller's responsibility to delete the listener. Returns
-// NULL if the listener is not found in the list.
-TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
- if (listener == default_result_printer_)
- default_result_printer_ = nullptr;
- else if (listener == default_xml_generator_)
- default_xml_generator_ = nullptr;
- return repeater_->Release(listener);
-}
-
-// Returns repeater that broadcasts the TestEventListener events to all
-// subscribers.
-TestEventListener* TestEventListeners::repeater() { return repeater_; }
-
-// Sets the default_result_printer attribute to the provided listener.
-// The listener is also added to the listener list and previous
-// default_result_printer is removed from it and deleted. The listener can
-// also be NULL in which case it will not be added to the list. Does
-// nothing if the previous and the current listener objects are the same.
-void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
- if (default_result_printer_ != listener) {
- // It is an error to pass this method a listener that is already in the
- // list.
- delete Release(default_result_printer_);
- default_result_printer_ = listener;
- if (listener != nullptr) Append(listener);
- }
-}
-
-// Sets the default_xml_generator attribute to the provided listener. The
-// listener is also added to the listener list and previous
-// default_xml_generator is removed from it and deleted. The listener can
-// also be NULL in which case it will not be added to the list. Does
-// nothing if the previous and the current listener objects are the same.
-void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
- if (default_xml_generator_ != listener) {
- // It is an error to pass this method a listener that is already in the
- // list.
- delete Release(default_xml_generator_);
- default_xml_generator_ = listener;
- if (listener != nullptr) Append(listener);
- }
-}
-
-// Controls whether events will be forwarded by the repeater to the
-// listeners in the list.
-bool TestEventListeners::EventForwardingEnabled() const {
- return repeater_->forwarding_enabled();
-}
-
-void TestEventListeners::SuppressEventForwarding() {
- repeater_->set_forwarding_enabled(false);
-}
-
-// class UnitTest
-
-// Gets the singleton UnitTest object. The first time this method is
-// called, a UnitTest object is constructed and returned. Consecutive
-// calls will return the same object.
-//
-// We don't protect this under mutex_ as a user is not supposed to
-// call this before main() starts, from which point on the return
-// value will never change.
-UnitTest* UnitTest::GetInstance() {
- // CodeGear C++Builder insists on a public destructor for the
- // default implementation. Use this implementation to keep good OO
- // design with private destructor.
-
-#if defined(__BORLANDC__)
- static UnitTest* const instance = new UnitTest;
- return instance;
-#else
- static UnitTest instance;
- return &instance;
-#endif // defined(__BORLANDC__)
-}
-
-// Gets the number of successful test suites.
-int UnitTest::successful_test_suite_count() const {
- return impl()->successful_test_suite_count();
-}
-
-// Gets the number of failed test suites.
-int UnitTest::failed_test_suite_count() const {
- return impl()->failed_test_suite_count();
-}
-
-// Gets the number of all test suites.
-int UnitTest::total_test_suite_count() const {
- return impl()->total_test_suite_count();
-}
-
-// Gets the number of all test suites that contain at least one test
-// that should run.
-int UnitTest::test_suite_to_run_count() const {
- return impl()->test_suite_to_run_count();
-}
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-int UnitTest::successful_test_case_count() const {
- return impl()->successful_test_suite_count();
-}
-int UnitTest::failed_test_case_count() const {
- return impl()->failed_test_suite_count();
-}
-int UnitTest::total_test_case_count() const {
- return impl()->total_test_suite_count();
-}
-int UnitTest::test_case_to_run_count() const {
- return impl()->test_suite_to_run_count();
-}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-// Gets the number of successful tests.
-int UnitTest::successful_test_count() const {
- return impl()->successful_test_count();
-}
-
-// Gets the number of skipped tests.
-int UnitTest::skipped_test_count() const {
- return impl()->skipped_test_count();
-}
-
-// Gets the number of failed tests.
-int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
-
-// Gets the number of disabled tests that will be reported in the XML report.
-int UnitTest::reportable_disabled_test_count() const {
- return impl()->reportable_disabled_test_count();
-}
-
-// Gets the number of disabled tests.
-int UnitTest::disabled_test_count() const {
- return impl()->disabled_test_count();
-}
-
-// Gets the number of tests to be printed in the XML report.
-int UnitTest::reportable_test_count() const {
- return impl()->reportable_test_count();
-}
-
-// Gets the number of all tests.
-int UnitTest::total_test_count() const { return impl()->total_test_count(); }
-
-// Gets the number of tests that should run.
-int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
-
-// Gets the time of the test program start, in ms from the start of the
-// UNIX epoch.
-internal::TimeInMillis UnitTest::start_timestamp() const {
- return impl()->start_timestamp();
-}
-
-// Gets the elapsed time, in milliseconds.
-internal::TimeInMillis UnitTest::elapsed_time() const {
- return impl()->elapsed_time();
-}
-
-// Returns true if and only if the unit test passed (i.e. all test suites
-// passed).
-bool UnitTest::Passed() const { return impl()->Passed(); }
-
-// Returns true if and only if the unit test failed (i.e. some test suite
-// failed or something outside of all tests failed).
-bool UnitTest::Failed() const { return impl()->Failed(); }
-
-// Gets the i-th test suite among all the test suites. i can range from 0 to
-// total_test_suite_count() - 1. If i is not in that range, returns NULL.
-const TestSuite* UnitTest::GetTestSuite(int i) const {
- return impl()->GetTestSuite(i);
-}
-
-// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-const TestCase* UnitTest::GetTestCase(int i) const {
- return impl()->GetTestCase(i);
-}
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
-// Returns the TestResult containing information on test failures and
-// properties logged outside of individual test suites.
-const TestResult& UnitTest::ad_hoc_test_result() const {
- return *impl()->ad_hoc_test_result();
-}
-
-// Gets the i-th test suite among all the test suites. i can range from 0 to
-// total_test_suite_count() - 1. If i is not in that range, returns NULL.
-TestSuite* UnitTest::GetMutableTestSuite(int i) {
- return impl()->GetMutableSuiteCase(i);
-}
-
-// Returns the list of event listeners that can be used to track events
-// inside Google Test.
-TestEventListeners& UnitTest::listeners() {
- return *impl()->listeners();
-}
-
-// Registers and returns a global test environment. When a test
-// program is run, all global test environments will be set-up in the
-// order they were registered. After all tests in the program have
-// finished, all global test environments will be torn-down in the
-// *reverse* order they were registered.
-//
-// The UnitTest object takes ownership of the given environment.
-//
-// We don't protect this under mutex_, as we only support calling it
-// from the main thread.
-Environment* UnitTest::AddEnvironment(Environment* env) {
- if (env == nullptr) {
- return nullptr;
- }
-
- impl_->environments().push_back(env);
- return env;
-}
-
-// Adds a TestPartResult to the current TestResult object. All Google Test
-// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
-// this to report their results. The user code should use the
-// assertion macros instead of calling this directly.
-void UnitTest::AddTestPartResult(
- TestPartResult::Type result_type,
- const char* file_name,
- int line_number,
- const std::string& message,
- const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) {
- Message msg;
- msg << message;
-
- internal::MutexLock lock(&mutex_);
- if (impl_->gtest_trace_stack().size() > 0) {
- msg << "\n" << GTEST_NAME_ << " trace:";
-
- for (size_t i = impl_->gtest_trace_stack().size(); i > 0; --i) {
- const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
- msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
- << " " << trace.message;
- }
- }
-
- if (os_stack_trace.c_str() != nullptr && !os_stack_trace.empty()) {
- msg << internal::kStackTraceMarker << os_stack_trace;
- }
-
- const TestPartResult result = TestPartResult(
- result_type, file_name, line_number, msg.GetString().c_str());
- impl_->GetTestPartResultReporterForCurrentThread()->
- ReportTestPartResult(result);
-
- if (result_type != TestPartResult::kSuccess &&
- result_type != TestPartResult::kSkip) {
- // gtest_break_on_failure takes precedence over
- // gtest_throw_on_failure. This allows a user to set the latter
- // in the code (perhaps in order to use Google Test assertions
- // with another testing framework) and specify the former on the
- // command line for debugging.
- if (GTEST_FLAG(break_on_failure)) {
-#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
- // Using DebugBreak on Windows allows gtest to still break into a debugger
- // when a failure happens and both the --gtest_break_on_failure and
- // the --gtest_catch_exceptions flags are specified.
- DebugBreak();
-#elif (!defined(__native_client__)) && \
- ((defined(__clang__) || defined(__GNUC__)) && \
- (defined(__x86_64__) || defined(__i386__)))
- // with clang/gcc we can achieve the same effect on x86 by invoking int3
- asm("int3");
-#else
- // Dereference nullptr through a volatile pointer to prevent the compiler
- // from removing. We use this rather than abort() or __builtin_trap() for
- // portability: some debuggers don't correctly trap abort().
- *static_cast<volatile int*>(nullptr) = 1;
-#endif // GTEST_OS_WINDOWS
- } else if (GTEST_FLAG(throw_on_failure)) {
-#if GTEST_HAS_EXCEPTIONS
- throw internal::GoogleTestFailureException(result);
-#else
- // We cannot call abort() as it generates a pop-up in debug mode
- // that cannot be suppressed in VC 7.1 or below.
- exit(1);
-#endif
- }
- }
-}
-
-// Adds a TestProperty to the current TestResult object when invoked from
-// inside a test, to current TestSuite's ad_hoc_test_result_ when invoked
-// from SetUpTestSuite or TearDownTestSuite, or to the global property set
-// when invoked elsewhere. If the result already contains a property with
-// the same key, the value will be updated.
-void UnitTest::RecordProperty(const std::string& key,
- const std::string& value) {
- impl_->RecordProperty(TestProperty(key, value));
-}
-
-// Runs all tests in this UnitTest object and prints the result.
-// Returns 0 if successful, or 1 otherwise.
-//
-// We don't protect this under mutex_, as we only support calling it
-// from the main thread.
-int UnitTest::Run() {
- const bool in_death_test_child_process =
- internal::GTEST_FLAG(internal_run_death_test).length() > 0;
-
- // Google Test implements this protocol for catching that a test
- // program exits before returning control to Google Test:
- //
- // 1. Upon start, Google Test creates a file whose absolute path
- // is specified by the environment variable
- // TEST_PREMATURE_EXIT_FILE.
- // 2. When Google Test has finished its work, it deletes the file.
- //
- // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
- // running a Google-Test-based test program and check the existence
- // of the file at the end of the test execution to see if it has
- // exited prematurely.
-
- // If we are in the child process of a death test, don't
- // create/delete the premature exit file, as doing so is unnecessary
- // and will confuse the parent process. Otherwise, create/delete
- // the file upon entering/leaving this function. If the program
- // somehow exits before this function has a chance to return, the
- // premature-exit file will be left undeleted, causing a test runner
- // that understands the premature-exit-file protocol to report the
- // test as having failed.
- const internal::ScopedPrematureExitFile premature_exit_file(
- in_death_test_child_process
- ? nullptr
- : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
-
- // Captures the value of GTEST_FLAG(catch_exceptions). This value will be
- // used for the duration of the program.
- impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
-
-#if GTEST_OS_WINDOWS
- // Either the user wants Google Test to catch exceptions thrown by the
- // tests or this is executing in the context of death test child
- // process. In either case the user does not want to see pop-up dialogs
- // about crashes - they are expected.
- if (impl()->catch_exceptions() || in_death_test_child_process) {
-# if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
- // SetErrorMode doesn't exist on CE.
- SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
- SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
-# endif // !GTEST_OS_WINDOWS_MOBILE
-
-# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
- // Death test children can be terminated with _abort(). On Windows,
- // _abort() can show a dialog with a warning message. This forces the
- // abort message to go to stderr instead.
- _set_error_mode(_OUT_TO_STDERR);
-# endif
-
-# if defined(_MSC_VER) && !GTEST_OS_WINDOWS_MOBILE
- // In the debug version, Visual Studio pops up a separate dialog
- // offering a choice to debug the aborted program. We need to suppress
- // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
- // executed. Google Test will notify the user of any unexpected
- // failure via stderr.
- if (!GTEST_FLAG(break_on_failure))
- _set_abort_behavior(
- 0x0, // Clear the following flags:
- _WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
-# endif
-
- // In debug mode, the Windows CRT can crash with an assertion over invalid
- // input (e.g. passing an invalid file descriptor). The default handling
- // for these assertions is to pop up a dialog and wait for user input.
- // Instead ask the CRT to dump such assertions to stderr non-interactively.
- if (!IsDebuggerPresent()) {
- (void)_CrtSetReportMode(_CRT_ASSERT,
- _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
- }
- }
-#endif // GTEST_OS_WINDOWS
-
- return internal::HandleExceptionsInMethodIfSupported(
- impl(),
- &internal::UnitTestImpl::RunAllTests,
- "auxiliary test code (environments or event listeners)") ? 0 : 1;
-}
-
-// Returns the working directory when the first TEST() or TEST_F() was
-// executed.
-const char* UnitTest::original_working_dir() const {
- return impl_->original_working_dir_.c_str();
-}
-
-// Returns the TestSuite object for the test that's currently running,
-// or NULL if no test is running.
-const TestSuite* UnitTest::current_test_suite() const
- GTEST_LOCK_EXCLUDED_(mutex_) {
- internal::MutexLock lock(&mutex_);
- return impl_->current_test_suite();
-}
-
-// Legacy API is still available but deprecated
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-const TestCase* UnitTest::current_test_case() const
- GTEST_LOCK_EXCLUDED_(mutex_) {
- internal::MutexLock lock(&mutex_);
- return impl_->current_test_suite();
-}
-#endif
-
-// Returns the TestInfo object for the test that's currently running,
-// or NULL if no test is running.
-const TestInfo* UnitTest::current_test_info() const
- GTEST_LOCK_EXCLUDED_(mutex_) {
- internal::MutexLock lock(&mutex_);
- return impl_->current_test_info();
-}
-
-// Returns the random seed used at the start of the current test run.
-int UnitTest::random_seed() const { return impl_->random_seed(); }
-
-// Returns ParameterizedTestSuiteRegistry object used to keep track of
-// value-parameterized tests and instantiate and register them.
-internal::ParameterizedTestSuiteRegistry&
-UnitTest::parameterized_test_registry() GTEST_LOCK_EXCLUDED_(mutex_) {
- return impl_->parameterized_test_registry();
-}
-
-// Creates an empty UnitTest.
-UnitTest::UnitTest() {
- impl_ = new internal::UnitTestImpl(this);
-}
-
-// Destructor of UnitTest.
-UnitTest::~UnitTest() {
- delete impl_;
-}
-
-// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
-// Google Test trace stack.
-void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
- GTEST_LOCK_EXCLUDED_(mutex_) {
- internal::MutexLock lock(&mutex_);
- impl_->gtest_trace_stack().push_back(trace);
-}
-
-// Pops a trace from the per-thread Google Test trace stack.
-void UnitTest::PopGTestTrace()
- GTEST_LOCK_EXCLUDED_(mutex_) {
- internal::MutexLock lock(&mutex_);
- impl_->gtest_trace_stack().pop_back();
-}
-
-namespace internal {
-
-UnitTestImpl::UnitTestImpl(UnitTest* parent)
- : parent_(parent),
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */)
- default_global_test_part_result_reporter_(this),
- default_per_thread_test_part_result_reporter_(this),
- GTEST_DISABLE_MSC_WARNINGS_POP_() global_test_part_result_repoter_(
- &default_global_test_part_result_reporter_),
- per_thread_test_part_result_reporter_(
- &default_per_thread_test_part_result_reporter_),
- parameterized_test_registry_(),
- parameterized_tests_registered_(false),
- last_death_test_suite_(-1),
- current_test_suite_(nullptr),
- current_test_info_(nullptr),
- ad_hoc_test_result_(),
- os_stack_trace_getter_(nullptr),
- post_flag_parse_init_performed_(false),
- random_seed_(0), // Will be overridden by the flag before first use.
- random_(0), // Will be reseeded before first use.
- start_timestamp_(0),
- elapsed_time_(0),
-#if GTEST_HAS_DEATH_TEST
- death_test_factory_(new DefaultDeathTestFactory),
-#endif
- // Will be overridden by the flag before first use.
- catch_exceptions_(false) {
- listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
-}
-
-UnitTestImpl::~UnitTestImpl() {
- // Deletes every TestSuite.
- ForEach(test_suites_, internal::Delete<TestSuite>);
-
- // Deletes every Environment.
- ForEach(environments_, internal::Delete<Environment>);
-
- delete os_stack_trace_getter_;
-}
-
-// Adds a TestProperty to the current TestResult object when invoked in a
-// context of a test, to current test suite's ad_hoc_test_result when invoke
-// from SetUpTestSuite/TearDownTestSuite, or to the global property set
-// otherwise. If the result already contains a property with the same key,
-// the value will be updated.
-void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
- std::string xml_element;
- TestResult* test_result; // TestResult appropriate for property recording.
-
- if (current_test_info_ != nullptr) {
- xml_element = "testcase";
- test_result = &(current_test_info_->result_);
- } else if (current_test_suite_ != nullptr) {
- xml_element = "testsuite";
- test_result = &(current_test_suite_->ad_hoc_test_result_);
- } else {
- xml_element = "testsuites";
- test_result = &ad_hoc_test_result_;
- }
- test_result->RecordProperty(xml_element, test_property);
-}
-
-#if GTEST_HAS_DEATH_TEST
-// Disables event forwarding if the control is currently in a death test
-// subprocess. Must not be called before InitGoogleTest.
-void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
- if (internal_run_death_test_flag_.get() != nullptr)
- listeners()->SuppressEventForwarding();
-}
-#endif // GTEST_HAS_DEATH_TEST
-
-// Initializes event listeners performing XML output as specified by
-// UnitTestOptions. Must not be called before InitGoogleTest.
-void UnitTestImpl::ConfigureXmlOutput() {
- const std::string& output_format = UnitTestOptions::GetOutputFormat();
- if (output_format == "xml") {
- listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
- UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
- } else if (output_format == "json") {
- listeners()->SetDefaultXmlGenerator(new JsonUnitTestResultPrinter(
- UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
- } else if (output_format != "") {
- GTEST_LOG_(WARNING) << "WARNING: unrecognized output format \""
- << output_format << "\" ignored.";
- }
-}
-
-#if GTEST_CAN_STREAM_RESULTS_
-// Initializes event listeners for streaming test results in string form.
-// Must not be called before InitGoogleTest.
-void UnitTestImpl::ConfigureStreamingOutput() {
- const std::string& target = GTEST_FLAG(stream_result_to);
- if (!target.empty()) {
- const size_t pos = target.find(':');
- if (pos != std::string::npos) {
- listeners()->Append(new StreamingListener(target.substr(0, pos),
- target.substr(pos+1)));
- } else {
- GTEST_LOG_(WARNING) << "unrecognized streaming target \"" << target
- << "\" ignored.";
- }
- }
-}
-#endif // GTEST_CAN_STREAM_RESULTS_
-
-// Performs initialization dependent upon flag values obtained in
-// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
-// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
-// this function is also called from RunAllTests. Since this function can be
-// called more than once, it has to be idempotent.
-void UnitTestImpl::PostFlagParsingInit() {
- // Ensures that this function does not execute more than once.
- if (!post_flag_parse_init_performed_) {
- post_flag_parse_init_performed_ = true;
-
-#if defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
- // Register to send notifications about key process state changes.
- listeners()->Append(new GTEST_CUSTOM_TEST_EVENT_LISTENER_());
-#endif // defined(GTEST_CUSTOM_TEST_EVENT_LISTENER_)
-
-#if GTEST_HAS_DEATH_TEST
- InitDeathTestSubprocessControlInfo();
- SuppressTestEventsIfInSubprocess();
-#endif // GTEST_HAS_DEATH_TEST
-
- // Registers parameterized tests. This makes parameterized tests
- // available to the UnitTest reflection API without running
- // RUN_ALL_TESTS.
- RegisterParameterizedTests();
-
- // Configures listeners for XML output. This makes it possible for users
- // to shut down the default XML output before invoking RUN_ALL_TESTS.
- ConfigureXmlOutput();
-
-#if GTEST_CAN_STREAM_RESULTS_
- // Configures listeners for streaming test results to the specified server.
- ConfigureStreamingOutput();
-#endif // GTEST_CAN_STREAM_RESULTS_
-
-#if GTEST_HAS_ABSL
- if (GTEST_FLAG(install_failure_signal_handler)) {
- absl::FailureSignalHandlerOptions options;
- absl::InstallFailureSignalHandler(options);
- }
-#endif // GTEST_HAS_ABSL
- }
-}
-
-// A predicate that checks the name of a TestSuite against a known
-// value.
-//
-// This is used for implementation of the UnitTest class only. We put
-// it in the anonymous namespace to prevent polluting the outer
-// namespace.
-//
-// TestSuiteNameIs is copyable.
-class TestSuiteNameIs {
- public:
- // Constructor.
- explicit TestSuiteNameIs(const std::string& name) : name_(name) {}
-
- // Returns true if and only if the name of test_suite matches name_.
- bool operator()(const TestSuite* test_suite) const {
- return test_suite != nullptr &&
- strcmp(test_suite->name(), name_.c_str()) == 0;
- }
-
- private:
- std::string name_;
-};
-
-// Finds and returns a TestSuite with the given name. If one doesn't
-// exist, creates one and returns it. It's the CALLER'S
-// RESPONSIBILITY to ensure that this function is only called WHEN THE
-// TESTS ARE NOT SHUFFLED.
-//
-// Arguments:
-//
-// test_suite_name: name of the test suite
-// type_param: the name of the test suite's type parameter, or NULL if
-// this is not a typed or a type-parameterized test suite.
-// set_up_tc: pointer to the function that sets up the test suite
-// tear_down_tc: pointer to the function that tears down the test suite
-TestSuite* UnitTestImpl::GetTestSuite(
- const char* test_suite_name, const char* type_param,
- internal::SetUpTestSuiteFunc set_up_tc,
- internal::TearDownTestSuiteFunc tear_down_tc) {
- // Can we find a TestSuite with the given name?
- const auto test_suite =
- std::find_if(test_suites_.rbegin(), test_suites_.rend(),
- TestSuiteNameIs(test_suite_name));
-
- if (test_suite != test_suites_.rend()) return *test_suite;
-
- // No. Let's create one.
- auto* const new_test_suite =
- new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);
-
- // Is this a death test suite?
- if (internal::UnitTestOptions::MatchesFilter(test_suite_name,
- kDeathTestSuiteFilter)) {
- // Yes. Inserts the test suite after the last death test suite
- // defined so far. This only works when the test suites haven't
- // been shuffled. Otherwise we may end up running a death test
- // after a non-death test.
- ++last_death_test_suite_;
- test_suites_.insert(test_suites_.begin() + last_death_test_suite_,
- new_test_suite);
- } else {
- // No. Appends to the end of the list.
- test_suites_.push_back(new_test_suite);
- }
-
- test_suite_indices_.push_back(static_cast<int>(test_suite_indices_.size()));
- return new_test_suite;
-}
-
-// Helpers for setting up / tearing down the given environment. They
-// are for use in the ForEach() function.
-static void SetUpEnvironment(Environment* env) { env->SetUp(); }
-static void TearDownEnvironment(Environment* env) { env->TearDown(); }
-
-// Runs all tests in this UnitTest object, prints the result, and
-// returns true if all tests are successful. If any exception is
-// thrown during a test, the test is considered to be failed, but the
-// rest of the tests will still be run.
-//
-// When parameterized tests are enabled, it expands and registers
-// parameterized tests first in RegisterParameterizedTests().
-// All other functions called from RunAllTests() may safely assume that
-// parameterized tests are ready to be counted and run.
-bool UnitTestImpl::RunAllTests() {
- // True if and only if Google Test is initialized before RUN_ALL_TESTS() is
- // called.
- const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized();
-
- // Do not run any test if the --help flag was specified.
- if (g_help_flag)
- return true;
-
- // Repeats the call to the post-flag parsing initialization in case the
- // user didn't call InitGoogleTest.
- PostFlagParsingInit();
-
- // Even if sharding is not on, test runners may want to use the
- // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
- // protocol.
- internal::WriteToShardStatusFileIfNeeded();
-
- // True if and only if we are in a subprocess for running a thread-safe-style
- // death test.
- bool in_subprocess_for_death_test = false;
-
-#if GTEST_HAS_DEATH_TEST
- in_subprocess_for_death_test =
- (internal_run_death_test_flag_.get() != nullptr);
-# if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
- if (in_subprocess_for_death_test) {
- GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_();
- }
-# endif // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)
-#endif // GTEST_HAS_DEATH_TEST
-
- const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
- in_subprocess_for_death_test);
-
- // Compares the full test names with the filter to decide which
- // tests to run.
- const bool has_tests_to_run = FilterTests(should_shard
- ? HONOR_SHARDING_PROTOCOL
- : IGNORE_SHARDING_PROTOCOL) > 0;
-
- // Lists the tests and exits if the --gtest_list_tests flag was specified.
- if (GTEST_FLAG(list_tests)) {
- // This must be called *after* FilterTests() has been called.
- ListTestsMatchingFilter();
- return true;
- }
-
- random_seed_ = GTEST_FLAG(shuffle) ?
- GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
-
- // True if and only if at least one test has failed.
- bool failed = false;
-
- TestEventListener* repeater = listeners()->repeater();
-
- start_timestamp_ = GetTimeInMillis();
- repeater->OnTestProgramStart(*parent_);
-
- // How many times to repeat the tests? We don't want to repeat them
- // when we are inside the subprocess of a death test.
- const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
- // Repeats forever if the repeat count is negative.
- const bool gtest_repeat_forever = repeat < 0;
- for (int i = 0; gtest_repeat_forever || i != repeat; i++) {
- // We want to preserve failures generated by ad-hoc test
- // assertions executed before RUN_ALL_TESTS().
- ClearNonAdHocTestResult();
-
- const TimeInMillis start = GetTimeInMillis();
-
- // Shuffles test suites and tests if requested.
- if (has_tests_to_run && GTEST_FLAG(shuffle)) {
- random()->Reseed(static_cast<UInt32>(random_seed_));
- // This should be done before calling OnTestIterationStart(),
- // such that a test event listener can see the actual test order
- // in the event.
- ShuffleTests();
- }
-
- // Tells the unit test event listeners that the tests are about to start.
- repeater->OnTestIterationStart(*parent_, i);
-
- // Runs each test suite if there is at least one test to run.
- if (has_tests_to_run) {
- // Sets up all environments beforehand.
- repeater->OnEnvironmentsSetUpStart(*parent_);
- ForEach(environments_, SetUpEnvironment);
- repeater->OnEnvironmentsSetUpEnd(*parent_);
-
- // Runs the tests only if there was no fatal failure or skip triggered
- // during global set-up.
- if (Test::IsSkipped()) {
- // Emit diagnostics when global set-up calls skip, as it will not be
- // emitted by default.
- TestResult& test_result =
- *internal::GetUnitTestImpl()->current_test_result();
- for (int j = 0; j < test_result.total_part_count(); ++j) {
- const TestPartResult& test_part_result =
- test_result.GetTestPartResult(j);
- if (test_part_result.type() == TestPartResult::kSkip) {
- const std::string& result = test_part_result.message();
- printf("%s\n", result.c_str());
- }
- }
- fflush(stdout);
- } else if (!Test::HasFatalFailure()) {
- for (int test_index = 0; test_index < total_test_suite_count();
- test_index++) {
- GetMutableSuiteCase(test_index)->Run();
- }
- }
-
- // Tears down all environments in reverse order afterwards.
- repeater->OnEnvironmentsTearDownStart(*parent_);
- std::for_each(environments_.rbegin(), environments_.rend(),
- TearDownEnvironment);
- repeater->OnEnvironmentsTearDownEnd(*parent_);
- }
-
- elapsed_time_ = GetTimeInMillis() - start;
-
- // Tells the unit test event listener that the tests have just finished.
- repeater->OnTestIterationEnd(*parent_, i);
-
- // Gets the result and clears it.
- if (!Passed()) {
- failed = true;
- }
-
- // Restores the original test order after the iteration. This
- // allows the user to quickly repro a failure that happens in the
- // N-th iteration without repeating the first (N - 1) iterations.
- // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
- // case the user somehow changes the value of the flag somewhere
- // (it's always safe to unshuffle the tests).
- UnshuffleTests();
-
- if (GTEST_FLAG(shuffle)) {
- // Picks a new random seed for each iteration.
- random_seed_ = GetNextRandomSeed(random_seed_);
- }
- }
-
- repeater->OnTestProgramEnd(*parent_);
-
- if (!gtest_is_initialized_before_run_all_tests) {
- ColoredPrintf(
- COLOR_RED,
- "\nIMPORTANT NOTICE - DO NOT IGNORE:\n"
- "This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_
- "() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_
- " will start to enforce the valid usage. "
- "Please fix it ASAP, or IT WILL START TO FAIL.\n"); // NOLINT
-#if GTEST_FOR_GOOGLE_
- ColoredPrintf(COLOR_RED,
- "For more details, see http://wiki/Main/ValidGUnitMain.\n");
-#endif // GTEST_FOR_GOOGLE_
- }
-
- return !failed;
-}
-
-// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
-// if the variable is present. If a file already exists at this location, this
-// function will write over it. If the variable is present, but the file cannot
-// be created, prints an error and exits.
-void WriteToShardStatusFileIfNeeded() {
- const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
- if (test_shard_file != nullptr) {
- FILE* const file = posix::FOpen(test_shard_file, "w");
- if (file == nullptr) {
- ColoredPrintf(COLOR_RED,
- "Could not write to the test shard status file \"%s\" "
- "specified by the %s environment variable.\n",
- test_shard_file, kTestShardStatusFile);
- fflush(stdout);
- exit(EXIT_FAILURE);
- }
- fclose(file);
- }
-}
-
-// Checks whether sharding is enabled by examining the relevant
-// environment variable values. If the variables are present,
-// but inconsistent (i.e., shard_index >= total_shards), prints
-// an error and exits. If in_subprocess_for_death_test, sharding is
-// disabled because it must only be applied to the original test
-// process. Otherwise, we could filter out death tests we intended to execute.
-bool ShouldShard(const char* total_shards_env,
- const char* shard_index_env,
- bool in_subprocess_for_death_test) {
- if (in_subprocess_for_death_test) {
- return false;
- }
-
- const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
- const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
-
- if (total_shards == -1 && shard_index == -1) {
- return false;
- } else if (total_shards == -1 && shard_index != -1) {
- const Message msg = Message()
- << "Invalid environment variables: you have "
- << kTestShardIndex << " = " << shard_index
- << ", but have left " << kTestTotalShards << " unset.\n";
- ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str());
- fflush(stdout);
- exit(EXIT_FAILURE);
- } else if (total_shards != -1 && shard_index == -1) {
- const Message msg = Message()
- << "Invalid environment variables: you have "
- << kTestTotalShards << " = " << total_shards
- << ", but have left " << kTestShardIndex << " unset.\n";
- ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str());
- fflush(stdout);
- exit(EXIT_FAILURE);
- } else if (shard_index < 0 || shard_index >= total_shards) {
- const Message msg = Message()
- << "Invalid environment variables: we require 0 <= "
- << kTestShardIndex << " < " << kTestTotalShards
- << ", but you have " << kTestShardIndex << "=" << shard_index
- << ", " << kTestTotalShards << "=" << total_shards << ".\n";
- ColoredPrintf(COLOR_RED, "%s", msg.GetString().c_str());
- fflush(stdout);
- exit(EXIT_FAILURE);
- }
-
- return total_shards > 1;
-}
-
-// Parses the environment variable var as an Int32. If it is unset,
-// returns default_val. If it is not an Int32, prints an error
-// and aborts.
-Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
- const char* str_val = posix::GetEnv(var);
- if (str_val == nullptr) {
- return default_val;
- }
-
- Int32 result;
- if (!ParseInt32(Message() << "The value of environment variable " << var,
- str_val, &result)) {
- exit(EXIT_FAILURE);
- }
- return result;
-}
-
-// Given the total number of shards, the shard index, and the test id,
-// returns true if and only if the test should be run on this shard. The test id
-// is some arbitrary but unique non-negative integer assigned to each test
-// method. Assumes that 0 <= shard_index < total_shards.
-bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
- return (test_id % total_shards) == shard_index;
-}
-
-// Compares the name of each test with the user-specified filter to
-// decide whether the test should be run, then records the result in
-// each TestSuite and TestInfo object.
-// If shard_tests == true, further filters tests based on sharding
-// variables in the environment - see
-// https://github.com/google/googletest/blob/master/googletest/docs/advanced.md
-// . Returns the number of tests that should run.
-int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
- const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
- Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
- const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
- Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
-
- // num_runnable_tests are the number of tests that will
- // run across all shards (i.e., match filter and are not disabled).
- // num_selected_tests are the number of tests to be run on
- // this shard.
- int num_runnable_tests = 0;
- int num_selected_tests = 0;
- for (auto* test_suite : test_suites_) {
- const std::string& test_suite_name = test_suite->name();
- test_suite->set_should_run(false);
-
- for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
- TestInfo* const test_info = test_suite->test_info_list()[j];
- const std::string test_name(test_info->name());
- // A test is disabled if test suite name or test name matches
- // kDisableTestFilter.
- const bool is_disabled = internal::UnitTestOptions::MatchesFilter(
- test_suite_name, kDisableTestFilter) ||
- internal::UnitTestOptions::MatchesFilter(
- test_name, kDisableTestFilter);
- test_info->is_disabled_ = is_disabled;
-
- const bool matches_filter = internal::UnitTestOptions::FilterMatchesTest(
- test_suite_name, test_name);
- test_info->matches_filter_ = matches_filter;
-
- const bool is_runnable =
- (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
- matches_filter;
-
- const bool is_in_another_shard =
- shard_tests != IGNORE_SHARDING_PROTOCOL &&
- !ShouldRunTestOnShard(total_shards, shard_index, num_runnable_tests);
- test_info->is_in_another_shard_ = is_in_another_shard;
- const bool is_selected = is_runnable && !is_in_another_shard;
-
- num_runnable_tests += is_runnable;
- num_selected_tests += is_selected;
-
- test_info->should_run_ = is_selected;
- test_suite->set_should_run(test_suite->should_run() || is_selected);
- }
- }
- return num_selected_tests;
-}
-
-// Prints the given C-string on a single line by replacing all '\n'
-// characters with string "\\n". If the output takes more than
-// max_length characters, only prints the first max_length characters
-// and "...".
-static void PrintOnOneLine(const char* str, int max_length) {
- if (str != nullptr) {
- for (int i = 0; *str != '\0'; ++str) {
- if (i >= max_length) {
- printf("...");
- break;
- }
- if (*str == '\n') {
- printf("\\n");
- i += 2;
- } else {
- printf("%c", *str);
- ++i;
- }
- }
- }
-}
-
-// Prints the names of the tests matching the user-specified filter flag.
-void UnitTestImpl::ListTestsMatchingFilter() {
- // Print at most this many characters for each type/value parameter.
- const int kMaxParamLength = 250;
-
- for (auto* test_suite : test_suites_) {
- bool printed_test_suite_name = false;
-
- for (size_t j = 0; j < test_suite->test_info_list().size(); j++) {
- const TestInfo* const test_info = test_suite->test_info_list()[j];
- if (test_info->matches_filter_) {
- if (!printed_test_suite_name) {
- printed_test_suite_name = true;
- printf("%s.", test_suite->name());
- if (test_suite->type_param() != nullptr) {
- printf(" # %s = ", kTypeParamLabel);
- // We print the type parameter on a single line to make
- // the output easy to parse by a program.
- PrintOnOneLine(test_suite->type_param(), kMaxParamLength);
- }
- printf("\n");
- }
- printf(" %s", test_info->name());
- if (test_info->value_param() != nullptr) {
- printf(" # %s = ", kValueParamLabel);
- // We print the value parameter on a single line to make the
- // output easy to parse by a program.
- PrintOnOneLine(test_info->value_param(), kMaxParamLength);
- }
- printf("\n");
- }
- }
- }
- fflush(stdout);
- const std::string& output_format = UnitTestOptions::GetOutputFormat();
- if (output_format == "xml" || output_format == "json") {
- FILE* fileout = OpenFileForWriting(
- UnitTestOptions::GetAbsolutePathToOutputFile().c_str());
- std::stringstream stream;
- if (output_format == "xml") {
- XmlUnitTestResultPrinter(
- UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
- .PrintXmlTestsList(&stream, test_suites_);
- } else if (output_format == "json") {
- JsonUnitTestResultPrinter(
- UnitTestOptions::GetAbsolutePathToOutputFile().c_str())
- .PrintJsonTestList(&stream, test_suites_);
- }
- fprintf(fileout, "%s", StringStreamToString(&stream).c_str());
- fclose(fileout);
- }
-}
-
-// Sets the OS stack trace getter.
-//
-// Does nothing if the input and the current OS stack trace getter are
-// the same; otherwise, deletes the old getter and makes the input the
-// current getter.
-void UnitTestImpl::set_os_stack_trace_getter(
- OsStackTraceGetterInterface* getter) {
- if (os_stack_trace_getter_ != getter) {
- delete os_stack_trace_getter_;
- os_stack_trace_getter_ = getter;
- }
-}
-
-// Returns the current OS stack trace getter if it is not NULL;
-// otherwise, creates an OsStackTraceGetter, makes it the current
-// getter, and returns it.
-OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
- if (os_stack_trace_getter_ == nullptr) {
-#ifdef GTEST_OS_STACK_TRACE_GETTER_
- os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_;
-#else
- os_stack_trace_getter_ = new OsStackTraceGetter;
-#endif // GTEST_OS_STACK_TRACE_GETTER_
- }
-
- return os_stack_trace_getter_;
-}
-
-// Returns the most specific TestResult currently running.
-TestResult* UnitTestImpl::current_test_result() {
- if (current_test_info_ != nullptr) {
- return ¤t_test_info_->result_;
- }
- if (current_test_suite_ != nullptr) {
- return ¤t_test_suite_->ad_hoc_test_result_;
- }
- return &ad_hoc_test_result_;
-}
-
-// Shuffles all test suites, and the tests within each test suite,
-// making sure that death tests are still run first.
-void UnitTestImpl::ShuffleTests() {
- // Shuffles the death test suites.
- ShuffleRange(random(), 0, last_death_test_suite_ + 1, &test_suite_indices_);
-
- // Shuffles the non-death test suites.
- ShuffleRange(random(), last_death_test_suite_ + 1,
- static_cast<int>(test_suites_.size()), &test_suite_indices_);
-
- // Shuffles the tests inside each test suite.
- for (auto& test_suite : test_suites_) {
- test_suite->ShuffleTests(random());
- }
-}
-
-// Restores the test suites and tests to their order before the first shuffle.
-void UnitTestImpl::UnshuffleTests() {
- for (size_t i = 0; i < test_suites_.size(); i++) {
- // Unshuffles the tests in each test suite.
- test_suites_[i]->UnshuffleTests();
- // Resets the index of each test suite.
- test_suite_indices_[i] = static_cast<int>(i);
- }
-}
-
-// Returns the current OS stack trace as an std::string.
-//
-// The maximum number of stack frames to be included is specified by
-// the gtest_stack_trace_depth flag. The skip_count parameter
-// specifies the number of top frames to be skipped, which doesn't
-// count against the number of frames to be included.
-//
-// For example, if Foo() calls Bar(), which in turn calls
-// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
-// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
-std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
- int skip_count) {
- // We pass skip_count + 1 to skip this wrapper function in addition
- // to what the user really wants to skip.
- return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
-}
-
-// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
-// suppress unreachable code warnings.
-namespace {
-class ClassUniqueToAlwaysTrue {};
-}
-
-bool IsTrue(bool condition) { return condition; }
-
-bool AlwaysTrue() {
-#if GTEST_HAS_EXCEPTIONS
- // This condition is always false so AlwaysTrue() never actually throws,
- // but it makes the compiler think that it may throw.
- if (IsTrue(false))
- throw ClassUniqueToAlwaysTrue();
-#endif // GTEST_HAS_EXCEPTIONS
- return true;
-}
-
-// If *pstr starts with the given prefix, modifies *pstr to be right
-// past the prefix and returns true; otherwise leaves *pstr unchanged
-// and returns false. None of pstr, *pstr, and prefix can be NULL.
-bool SkipPrefix(const char* prefix, const char** pstr) {
- const size_t prefix_len = strlen(prefix);
- if (strncmp(*pstr, prefix, prefix_len) == 0) {
- *pstr += prefix_len;
- return true;
- }
- return false;
-}
-
-// Parses a string as a command line flag. The string should have
-// the format "--flag=value". When def_optional is true, the "=value"
-// part can be omitted.
-//
-// Returns the value of the flag, or NULL if the parsing failed.
-static const char* ParseFlagValue(const char* str, const char* flag,
- bool def_optional) {
- // str and flag must not be NULL.
- if (str == nullptr || flag == nullptr) return nullptr;
-
- // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
- const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag;
- const size_t flag_len = flag_str.length();
- if (strncmp(str, flag_str.c_str(), flag_len) != 0) return nullptr;
-
- // Skips the flag name.
- const char* flag_end = str + flag_len;
-
- // When def_optional is true, it's OK to not have a "=value" part.
- if (def_optional && (flag_end[0] == '\0')) {
- return flag_end;
- }
-
- // If def_optional is true and there are more characters after the
- // flag name, or if def_optional is false, there must be a '=' after
- // the flag name.
- if (flag_end[0] != '=') return nullptr;
-
- // Returns the string after "=".
- return flag_end + 1;
-}
-
-// Parses a string for a bool flag, in the form of either
-// "--flag=value" or "--flag".
-//
-// In the former case, the value is taken as true as long as it does
-// not start with '0', 'f', or 'F'.
-//
-// In the latter case, the value is taken as true.
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-static bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, true);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- // Converts the string value to a bool.
- *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
- return true;
-}
-
-// Parses a string for an Int32 flag, in the form of
-// "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, false);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- // Sets *value to the value of the flag.
- return ParseInt32(Message() << "The value of flag --" << flag,
- value_str, value);
-}
-
-// Parses a string for a string flag, in the form of
-// "--flag=value".
-//
-// On success, stores the value of the flag in *value, and returns
-// true. On failure, returns false without changing *value.
-template <typename String>
-static bool ParseStringFlag(const char* str, const char* flag, String* value) {
- // Gets the value of the flag as a string.
- const char* const value_str = ParseFlagValue(str, flag, false);
-
- // Aborts if the parsing failed.
- if (value_str == nullptr) return false;
-
- // Sets *value to the value of the flag.
- *value = value_str;
- return true;
-}
-
-// Determines whether a string has a prefix that Google Test uses for its
-// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
-// If Google Test detects that a command line flag has its prefix but is not
-// recognized, it will print its help message. Flags starting with
-// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
-// internal flags and do not trigger the help message.
-static bool HasGoogleTestFlagPrefix(const char* str) {
- return (SkipPrefix("--", &str) ||
- SkipPrefix("-", &str) ||
- SkipPrefix("/", &str)) &&
- !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
- (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
- SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
-}
-
-// Prints a string containing code-encoded text. The following escape
-// sequences can be used in the string to control the text color:
-//
-// @@ prints a single '@' character.
-// @R changes the color to red.
-// @G changes the color to green.
-// @Y changes the color to yellow.
-// @D changes to the default terminal text color.
-//
-static void PrintColorEncoded(const char* str) {
- GTestColor color = COLOR_DEFAULT; // The current color.
-
- // Conceptually, we split the string into segments divided by escape
- // sequences. Then we print one segment at a time. At the end of
- // each iteration, the str pointer advances to the beginning of the
- // next segment.
- for (;;) {
- const char* p = strchr(str, '@');
- if (p == nullptr) {
- ColoredPrintf(color, "%s", str);
- return;
- }
-
- ColoredPrintf(color, "%s", std::string(str, p).c_str());
-
- const char ch = p[1];
- str = p + 2;
- if (ch == '@') {
- ColoredPrintf(color, "@");
- } else if (ch == 'D') {
- color = COLOR_DEFAULT;
- } else if (ch == 'R') {
- color = COLOR_RED;
- } else if (ch == 'G') {
- color = COLOR_GREEN;
- } else if (ch == 'Y') {
- color = COLOR_YELLOW;
- } else {
- --str;
- }
- }
-}
-
-static const char kColorEncodedHelpMessage[] =
-"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
-"following command line flags to control its behavior:\n"
-"\n"
-"Test Selection:\n"
-" @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
-" List the names of all tests instead of running them. The name of\n"
-" TEST(Foo, Bar) is \"Foo.Bar\".\n"
-" @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
- "[@G-@YNEGATIVE_PATTERNS]@D\n"
-" Run only the tests whose name matches one of the positive patterns but\n"
-" none of the negative patterns. '?' matches any single character; '*'\n"
-" matches any substring; ':' separates two patterns.\n"
-" @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
-" Run all disabled tests too.\n"
-"\n"
-"Test Execution:\n"
-" @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
-" Run the tests repeatedly; use a negative count to repeat forever.\n"
-" @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
-" Randomize tests' orders on every iteration.\n"
-" @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
-" Random number seed to use for shuffling test orders (between 1 and\n"
-" 99999, or 0 to use a seed based on the current time).\n"
-"\n"
-"Test Output:\n"
-" @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
-" Enable/disable colored output. The default is @Gauto@D.\n"
-" -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
-" Don't print the elapsed time of each test.\n"
-" @G--" GTEST_FLAG_PREFIX_ "output=@Y(@Gjson@Y|@Gxml@Y)[@G:@YDIRECTORY_PATH@G"
- GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
-" Generate a JSON or XML report in the given directory or with the given\n"
-" file name. @YFILE_PATH@D defaults to @Gtest_detail.xml@D.\n"
-# if GTEST_CAN_STREAM_RESULTS_
-" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
-" Stream test results to the given server.\n"
-# endif // GTEST_CAN_STREAM_RESULTS_
-"\n"
-"Assertion Behavior:\n"
-# if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
-" @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
-" Set the default death test style.\n"
-# endif // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
-" @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
-" Turn assertion failures into debugger break-points.\n"
-" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
-" Turn assertion failures into C++ exceptions for use by an external\n"
-" test framework.\n"
-" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
-" Do not report exceptions as test failures. Instead, allow them\n"
-" to crash the program or throw a pop-up (on Windows).\n"
-"\n"
-"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
- "the corresponding\n"
-"environment variable of a flag (all letters in upper-case). For example, to\n"
-"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
- "color=no@D or set\n"
-"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
-"\n"
-"For more information, please read the " GTEST_NAME_ " documentation at\n"
-"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
-"(not one in your own code or tests), please report it to\n"
-"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
-
-static bool ParseGoogleTestFlag(const char* const arg) {
- return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
- >EST_FLAG(also_run_disabled_tests)) ||
- ParseBoolFlag(arg, kBreakOnFailureFlag,
- >EST_FLAG(break_on_failure)) ||
- ParseBoolFlag(arg, kCatchExceptionsFlag,
- >EST_FLAG(catch_exceptions)) ||
- ParseStringFlag(arg, kColorFlag, >EST_FLAG(color)) ||
- ParseStringFlag(arg, kDeathTestStyleFlag,
- >EST_FLAG(death_test_style)) ||
- ParseBoolFlag(arg, kDeathTestUseFork,
- >EST_FLAG(death_test_use_fork)) ||
- ParseStringFlag(arg, kFilterFlag, >EST_FLAG(filter)) ||
- ParseStringFlag(arg, kInternalRunDeathTestFlag,
- >EST_FLAG(internal_run_death_test)) ||
- ParseBoolFlag(arg, kListTestsFlag, >EST_FLAG(list_tests)) ||
- ParseStringFlag(arg, kOutputFlag, >EST_FLAG(output)) ||
- ParseBoolFlag(arg, kPrintTimeFlag, >EST_FLAG(print_time)) ||
- ParseBoolFlag(arg, kPrintUTF8Flag, >EST_FLAG(print_utf8)) ||
- ParseInt32Flag(arg, kRandomSeedFlag, >EST_FLAG(random_seed)) ||
- ParseInt32Flag(arg, kRepeatFlag, >EST_FLAG(repeat)) ||
- ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) ||
- ParseInt32Flag(arg, kStackTraceDepthFlag,
- >EST_FLAG(stack_trace_depth)) ||
- ParseStringFlag(arg, kStreamResultToFlag,
- >EST_FLAG(stream_result_to)) ||
- ParseBoolFlag(arg, kThrowOnFailureFlag,
- >EST_FLAG(throw_on_failure));
-}
-
-#if GTEST_USE_OWN_FLAGFILE_FLAG_
-static void LoadFlagsFromFile(const std::string& path) {
- FILE* flagfile = posix::FOpen(path.c_str(), "r");
- if (!flagfile) {
- GTEST_LOG_(FATAL) << "Unable to open file \"" << GTEST_FLAG(flagfile)
- << "\"";
- }
- std::string contents(ReadEntireFile(flagfile));
- posix::FClose(flagfile);
- std::vector<std::string> lines;
- SplitString(contents, '\n', &lines);
- for (size_t i = 0; i < lines.size(); ++i) {
- if (lines[i].empty())
- continue;
- if (!ParseGoogleTestFlag(lines[i].c_str()))
- g_help_flag = true;
- }
-}
-#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
-
-// Parses the command line for Google Test flags, without initializing
-// other parts of Google Test. The type parameter CharType can be
-// instantiated to either char or wchar_t.
-template <typename CharType>
-void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
- for (int i = 1; i < *argc; i++) {
- const std::string arg_string = StreamableToString(argv[i]);
- const char* const arg = arg_string.c_str();
-
- using internal::ParseBoolFlag;
- using internal::ParseInt32Flag;
- using internal::ParseStringFlag;
-
- bool remove_flag = false;
- if (ParseGoogleTestFlag(arg)) {
- remove_flag = true;
-#if GTEST_USE_OWN_FLAGFILE_FLAG_
- } else if (ParseStringFlag(arg, kFlagfileFlag, >EST_FLAG(flagfile))) {
- LoadFlagsFromFile(GTEST_FLAG(flagfile));
- remove_flag = true;
-#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
- } else if (arg_string == "--help" || arg_string == "-h" ||
- arg_string == "-?" || arg_string == "/?" ||
- HasGoogleTestFlagPrefix(arg)) {
- // Both help flag and unrecognized Google Test flags (excluding
- // internal ones) trigger help display.
- g_help_flag = true;
- }
-
- if (remove_flag) {
- // Shift the remainder of the argv list left by one. Note
- // that argv has (*argc + 1) elements, the last one always being
- // NULL. The following loop moves the trailing NULL element as
- // well.
- for (int j = i; j != *argc; j++) {
- argv[j] = argv[j + 1];
- }
-
- // Decrements the argument count.
- (*argc)--;
-
- // We also need to decrement the iterator as we just removed
- // an element.
- i--;
- }
- }
-
- if (g_help_flag) {
- // We print the help here instead of in RUN_ALL_TESTS(), as the
- // latter may not be called at all if the user is using Google
- // Test with another testing framework.
- PrintColorEncoded(kColorEncodedHelpMessage);
- }
-}
-
-// Parses the command line for Google Test flags, without initializing
-// other parts of Google Test.
-void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
- ParseGoogleTestFlagsOnlyImpl(argc, argv);
-
- // Fix the value of *_NSGetArgc() on macOS, but if and only if
- // *_NSGetArgv() == argv
- // Only applicable to char** version of argv
-#if GTEST_OS_MAC
-#ifndef GTEST_OS_IOS
- if (*_NSGetArgv() == argv) {
- *_NSGetArgc() = *argc;
- }
-#endif
-#endif
-}
-void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
- ParseGoogleTestFlagsOnlyImpl(argc, argv);
-}
-
-// The internal implementation of InitGoogleTest().
-//
-// The type parameter CharType can be instantiated to either char or
-// wchar_t.
-template <typename CharType>
-void InitGoogleTestImpl(int* argc, CharType** argv) {
- // We don't want to run the initialization code twice.
- if (GTestIsInitialized()) return;
-
- if (*argc <= 0) return;
-
- g_argvs.clear();
- for (int i = 0; i != *argc; i++) {
- g_argvs.push_back(StreamableToString(argv[i]));
- }
-
-#if GTEST_HAS_ABSL
- absl::InitializeSymbolizer(g_argvs[0].c_str());
-#endif // GTEST_HAS_ABSL
-
- ParseGoogleTestFlagsOnly(argc, argv);
- GetUnitTestImpl()->PostFlagParsingInit();
-}
-
-} // namespace internal
-
-// Initializes Google Test. This must be called before calling
-// RUN_ALL_TESTS(). In particular, it parses a command line for the
-// flags that Google Test recognizes. Whenever a Google Test flag is
-// seen, it is removed from argv, and *argc is decremented.
-//
-// No value is returned. Instead, the Google Test flag variables are
-// updated.
-//
-// Calling the function for the second time has no user-visible effect.
-void InitGoogleTest(int* argc, char** argv) {
-#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
- GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
-#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
- internal::InitGoogleTestImpl(argc, argv);
-#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
-}
-
-// This overloaded version can be used in Windows programs compiled in
-// UNICODE mode.
-void InitGoogleTest(int* argc, wchar_t** argv) {
-#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
- GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(argc, argv);
-#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
- internal::InitGoogleTestImpl(argc, argv);
-#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
-}
-
-// This overloaded version can be used on Arduino/embedded platforms where
-// there is no argc/argv.
-void InitGoogleTest() {
- // Since Arduino doesn't have a command line, fake out the argc/argv arguments
- int argc = 1;
- const auto arg0 = "dummy";
- char* argv0 = const_cast<char*>(arg0);
- char** argv = &argv0;
-
-#if defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
- GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_(&argc, argv);
-#else // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
- internal::InitGoogleTestImpl(&argc, argv);
-#endif // defined(GTEST_CUSTOM_INIT_GOOGLE_TEST_FUNCTION_)
-}
-
-std::string TempDir() {
-#if defined(GTEST_CUSTOM_TEMPDIR_FUNCTION_)
- return GTEST_CUSTOM_TEMPDIR_FUNCTION_();
-#endif
-
-#if GTEST_OS_WINDOWS_MOBILE
- return "\\temp\\";
-#elif GTEST_OS_WINDOWS
- const char* temp_dir = internal::posix::GetEnv("TEMP");
- if (temp_dir == nullptr || temp_dir[0] == '\0')
- return "\\temp\\";
- else if (temp_dir[strlen(temp_dir) - 1] == '\\')
- return temp_dir;
- else
- return std::string(temp_dir) + "\\";
-#elif GTEST_OS_LINUX_ANDROID
- return "/sdcard/";
-#else
- return "/tmp/";
-#endif // GTEST_OS_WINDOWS_MOBILE
-}
-
-// Class ScopedTrace
-
-// Pushes the given source file location and message onto a per-thread
-// trace stack maintained by Google Test.
-void ScopedTrace::PushTrace(const char* file, int line, std::string message) {
- internal::TraceInfo trace;
- trace.file = file;
- trace.line = line;
- trace.message.swap(message);
-
- UnitTest::GetInstance()->PushGTestTrace(trace);
-}
-
-// Pops the info pushed by the c'tor.
-ScopedTrace::~ScopedTrace()
- GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
- UnitTest::GetInstance()->PopGTestTrace();
-}
-
-} // namespace testing
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <cstdio>
-#include "gtest/gtest.h"
-
-#ifdef ARDUINO
-void setup() {
- testing::InitGoogleTest();
-}
-
-void loop() { RUN_ALL_TESTS(); }
-
-#else
-
-GTEST_API_ int main(int argc, char **argv) {
- printf("Running main() from %s\n", __FILE__);
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-#endif
+++ /dev/null
-# Copyright 2017 Google Inc.
-# All Rights Reserved.
-#
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Author: misterg@google.com (Gennadiy Civil)
-#
-# Bazel BUILD for The Google C++ Testing Framework (Google Test)
-
-load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test")
-load("@rules_python//python:defs.bzl", "py_library", "py_test")
-
-licenses(["notice"])
-
-#on windows exclude gtest-tuple.h
-cc_test(
- name = "gtest_all_test",
- size = "small",
- srcs = glob(
- include = [
- "gtest-*.cc",
- "googletest-*.cc",
- "*.h",
- "googletest/include/gtest/**/*.h",
- ],
- exclude = [
- "gtest-unittest-api_test.cc",
- "googletest/src/gtest-all.cc",
- "gtest_all_test.cc",
- "gtest-death-test_ex_test.cc",
- "gtest-listener_test.cc",
- "gtest-unittest-api_test.cc",
- "googletest-param-test-test.cc",
- "googletest-catch-exceptions-test_.cc",
- "googletest-color-test_.cc",
- "googletest-env-var-test_.cc",
- "googletest-filter-unittest_.cc",
- "googletest-break-on-failure-unittest_.cc",
- "googletest-listener-test.cc",
- "googletest-output-test_.cc",
- "googletest-list-tests-unittest_.cc",
- "googletest-shuffle-test_.cc",
- "googletest-uninitialized-test_.cc",
- "googletest-death-test_ex_test.cc",
- "googletest-param-test-test",
- "googletest-throw-on-failure-test_.cc",
- "googletest-param-test-invalid-name1-test_.cc",
- "googletest-param-test-invalid-name2-test_.cc",
- ],
- ) + select({
- "//:windows": [],
- "//conditions:default": [],
- }),
- copts = select({
- "//:windows": ["-DGTEST_USE_OWN_TR1_TUPLE=0"],
- "//conditions:default": ["-DGTEST_USE_OWN_TR1_TUPLE=1"],
- }),
- includes = [
- "googletest",
- "googletest/include",
- "googletest/include/internal",
- "googletest/test",
- ],
- linkopts = select({
- "//:windows": [],
- "//conditions:default": ["-pthread"],
- }),
- deps = ["//:gtest_main"],
-)
-
-# Tests death tests.
-cc_test(
- name = "googletest-death-test-test",
- size = "medium",
- srcs = ["googletest-death-test-test.cc"],
- deps = ["//:gtest_main"],
-)
-
-cc_test(
- name = "gtest_test_macro_stack_footprint_test",
- size = "small",
- srcs = ["gtest_test_macro_stack_footprint_test.cc"],
- deps = ["//:gtest"],
-)
-
-#These googletest tests have their own main()
-cc_test(
- name = "googletest-listener-test",
- size = "small",
- srcs = ["googletest-listener-test.cc"],
- deps = ["//:gtest_main"],
-)
-
-cc_test(
- name = "gtest-unittest-api_test",
- size = "small",
- srcs = [
- "gtest-unittest-api_test.cc",
- ],
- deps = [
- "//:gtest",
- ],
-)
-
-cc_test(
- name = "googletest-param-test-test",
- size = "small",
- srcs = [
- "googletest-param-test-test.cc",
- "googletest-param-test-test.h",
- "googletest-param-test2-test.cc",
- ],
- deps = ["//:gtest"],
-)
-
-cc_test(
- name = "gtest_unittest",
- size = "small",
- srcs = ["gtest_unittest.cc"],
- args = ["--heap_check=strict"],
- shard_count = 2,
- deps = ["//:gtest_main"],
-)
-
-# Py tests
-
-py_library(
- name = "gtest_test_utils",
- testonly = 1,
- srcs = ["gtest_test_utils.py"],
-)
-
-cc_binary(
- name = "gtest_help_test_",
- testonly = 1,
- srcs = ["gtest_help_test_.cc"],
- deps = ["//:gtest_main"],
-)
-
-py_test(
- name = "gtest_help_test",
- size = "small",
- srcs = ["gtest_help_test.py"],
- data = [":gtest_help_test_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-output-test_",
- testonly = 1,
- srcs = ["googletest-output-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-output-test",
- size = "small",
- srcs = ["googletest-output-test.py"],
- args = select({
- "//:has_absl": [],
- "//conditions:default": ["--no_stacktrace_support"],
- }),
- data = [
- "googletest-output-test-golden-lin.txt",
- ":googletest-output-test_",
- ],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-color-test_",
- testonly = 1,
- srcs = ["googletest-color-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-color-test",
- size = "small",
- srcs = ["googletest-color-test.py"],
- data = [":googletest-color-test_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-env-var-test_",
- testonly = 1,
- srcs = ["googletest-env-var-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-env-var-test",
- size = "medium",
- srcs = ["googletest-env-var-test.py"],
- data = [":googletest-env-var-test_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-filter-unittest_",
- testonly = 1,
- srcs = ["googletest-filter-unittest_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-filter-unittest",
- size = "medium",
- srcs = ["googletest-filter-unittest.py"],
- data = [":googletest-filter-unittest_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-break-on-failure-unittest_",
- testonly = 1,
- srcs = ["googletest-break-on-failure-unittest_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-break-on-failure-unittest",
- size = "small",
- srcs = ["googletest-break-on-failure-unittest.py"],
- data = [":googletest-break-on-failure-unittest_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_test(
- name = "gtest_assert_by_exception_test",
- size = "small",
- srcs = ["gtest_assert_by_exception_test.cc"],
- deps = ["//:gtest"],
-)
-
-cc_binary(
- name = "googletest-throw-on-failure-test_",
- testonly = 1,
- srcs = ["googletest-throw-on-failure-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-throw-on-failure-test",
- size = "small",
- srcs = ["googletest-throw-on-failure-test.py"],
- data = [":googletest-throw-on-failure-test_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-list-tests-unittest_",
- testonly = 1,
- srcs = ["googletest-list-tests-unittest_.cc"],
- deps = ["//:gtest"],
-)
-
-cc_test(
- name = "gtest_skip_test",
- size = "small",
- srcs = ["gtest_skip_test.cc"],
- deps = ["//:gtest_main"],
-)
-
-cc_test(
- name = "gtest_skip_in_environment_setup_test",
- size = "small",
- srcs = ["gtest_skip_in_environment_setup_test.cc"],
- deps = ["//:gtest_main"],
-)
-
-py_test(
- name = "gtest_skip_environment_check_output_test",
- size = "small",
- srcs = ["gtest_skip_environment_check_output_test.py"],
- data = [
- ":gtest_skip_in_environment_setup_test",
- ],
- deps = [":gtest_test_utils"],
-)
-
-py_test(
- name = "googletest-list-tests-unittest",
- size = "small",
- srcs = ["googletest-list-tests-unittest.py"],
- data = [":googletest-list-tests-unittest_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-shuffle-test_",
- srcs = ["googletest-shuffle-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-shuffle-test",
- size = "small",
- srcs = ["googletest-shuffle-test.py"],
- data = [":googletest-shuffle-test_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-catch-exceptions-no-ex-test_",
- testonly = 1,
- srcs = ["googletest-catch-exceptions-test_.cc"],
- deps = ["//:gtest_main"],
-)
-
-cc_binary(
- name = "googletest-catch-exceptions-ex-test_",
- testonly = 1,
- srcs = ["googletest-catch-exceptions-test_.cc"],
- copts = ["-fexceptions"],
- deps = ["//:gtest_main"],
-)
-
-py_test(
- name = "googletest-catch-exceptions-test",
- size = "small",
- srcs = ["googletest-catch-exceptions-test.py"],
- data = [
- ":googletest-catch-exceptions-ex-test_",
- ":googletest-catch-exceptions-no-ex-test_",
- ],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "gtest_xml_output_unittest_",
- testonly = 1,
- srcs = ["gtest_xml_output_unittest_.cc"],
- deps = ["//:gtest"],
-)
-
-cc_test(
- name = "gtest_no_test_unittest",
- size = "small",
- srcs = ["gtest_no_test_unittest.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "gtest_xml_output_unittest",
- size = "small",
- srcs = [
- "gtest_xml_output_unittest.py",
- "gtest_xml_test_utils.py",
- ],
- args = select({
- "//:has_absl": [],
- "//conditions:default": ["--no_stacktrace_support"],
- }),
- data = [
- # We invoke gtest_no_test_unittest to verify the XML output
- # when the test program contains no test definition.
- ":gtest_no_test_unittest",
- ":gtest_xml_output_unittest_",
- ],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "gtest_xml_outfile1_test_",
- testonly = 1,
- srcs = ["gtest_xml_outfile1_test_.cc"],
- deps = ["//:gtest_main"],
-)
-
-cc_binary(
- name = "gtest_xml_outfile2_test_",
- testonly = 1,
- srcs = ["gtest_xml_outfile2_test_.cc"],
- deps = ["//:gtest_main"],
-)
-
-py_test(
- name = "gtest_xml_outfiles_test",
- size = "small",
- srcs = [
- "gtest_xml_outfiles_test.py",
- "gtest_xml_test_utils.py",
- ],
- data = [
- ":gtest_xml_outfile1_test_",
- ":gtest_xml_outfile2_test_",
- ],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "googletest-uninitialized-test_",
- testonly = 1,
- srcs = ["googletest-uninitialized-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-uninitialized-test",
- size = "medium",
- srcs = ["googletest-uninitialized-test.py"],
- data = ["googletest-uninitialized-test_"],
- deps = [":gtest_test_utils"],
-)
-
-cc_binary(
- name = "gtest_testbridge_test_",
- testonly = 1,
- srcs = ["gtest_testbridge_test_.cc"],
- deps = ["//:gtest_main"],
-)
-
-# Tests that filtering via testbridge works
-py_test(
- name = "gtest_testbridge_test",
- size = "small",
- srcs = ["gtest_testbridge_test.py"],
- data = [":gtest_testbridge_test_"],
- deps = [":gtest_test_utils"],
-)
-
-py_test(
- name = "googletest-json-outfiles-test",
- size = "small",
- srcs = [
- "googletest-json-outfiles-test.py",
- "gtest_json_test_utils.py",
- ],
- data = [
- ":gtest_xml_outfile1_test_",
- ":gtest_xml_outfile2_test_",
- ],
- deps = [":gtest_test_utils"],
-)
-
-py_test(
- name = "googletest-json-output-unittest",
- size = "medium",
- srcs = [
- "googletest-json-output-unittest.py",
- "gtest_json_test_utils.py",
- ],
- args = select({
- "//:has_absl": [],
- "//conditions:default": ["--no_stacktrace_support"],
- }),
- data = [
- # We invoke gtest_no_test_unittest to verify the JSON output
- # when the test program contains no test definition.
- ":gtest_no_test_unittest",
- ":gtest_xml_output_unittest_",
- ],
- deps = [":gtest_test_utils"],
-)
-
-# Verifies interaction of death tests and exceptions.
-cc_test(
- name = "googletest-death-test_ex_catch_test",
- size = "medium",
- srcs = ["googletest-death-test_ex_test.cc"],
- copts = ["-fexceptions"],
- defines = ["GTEST_ENABLE_CATCH_EXCEPTIONS_=1"],
- deps = ["//:gtest"],
-)
-
-cc_binary(
- name = "googletest-param-test-invalid-name1-test_",
- testonly = 1,
- srcs = ["googletest-param-test-invalid-name1-test_.cc"],
- deps = ["//:gtest"],
-)
-
-cc_binary(
- name = "googletest-param-test-invalid-name2-test_",
- testonly = 1,
- srcs = ["googletest-param-test-invalid-name2-test_.cc"],
- deps = ["//:gtest"],
-)
-
-py_test(
- name = "googletest-param-test-invalid-name1-test",
- size = "small",
- srcs = ["googletest-param-test-invalid-name1-test.py"],
- data = [":googletest-param-test-invalid-name1-test_"],
- deps = [":gtest_test_utils"],
-)
-
-py_test(
- name = "googletest-param-test-invalid-name2-test",
- size = "small",
- srcs = ["googletest-param-test-invalid-name2-test.py"],
- data = [":googletest-param-test-invalid-name2-test_"],
- deps = [":gtest_test_utils"],
-)
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for Google Test's break-on-failure mode.
-
-A user can ask Google Test to seg-fault when an assertion fails, using
-either the GTEST_BREAK_ON_FAILURE environment variable or the
---gtest_break_on_failure flag. This script tests such functionality
-by invoking googletest-break-on-failure-unittest_ (a program written with
-Google Test) with different environments and command line flags.
-"""
-
-import os
-import gtest_test_utils
-
-# Constants.
-
-IS_WINDOWS = os.name == 'nt'
-
-# The environment variable for enabling/disabling the break-on-failure mode.
-BREAK_ON_FAILURE_ENV_VAR = 'GTEST_BREAK_ON_FAILURE'
-
-# The command line flag for enabling/disabling the break-on-failure mode.
-BREAK_ON_FAILURE_FLAG = 'gtest_break_on_failure'
-
-# The environment variable for enabling/disabling the throw-on-failure mode.
-THROW_ON_FAILURE_ENV_VAR = 'GTEST_THROW_ON_FAILURE'
-
-# The environment variable for enabling/disabling the catch-exceptions mode.
-CATCH_EXCEPTIONS_ENV_VAR = 'GTEST_CATCH_EXCEPTIONS'
-
-# Path to the googletest-break-on-failure-unittest_ program.
-EXE_PATH = gtest_test_utils.GetTestExecutablePath(
- 'googletest-break-on-failure-unittest_')
-
-
-environ = gtest_test_utils.environ
-SetEnvVar = gtest_test_utils.SetEnvVar
-
-# Tests in this file run a Google-Test-based test program and expect it
-# to terminate prematurely. Therefore they are incompatible with
-# the premature-exit-file protocol by design. Unset the
-# premature-exit filepath to prevent Google Test from creating
-# the file.
-SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
-
-
-def Run(command):
- """Runs a command; returns 1 if it was killed by a signal, or 0 otherwise."""
-
- p = gtest_test_utils.Subprocess(command, env=environ)
- if p.terminated_by_signal:
- return 1
- else:
- return 0
-
-
-# The tests.
-
-
-class GTestBreakOnFailureUnitTest(gtest_test_utils.TestCase):
- """Tests using the GTEST_BREAK_ON_FAILURE environment variable or
- the --gtest_break_on_failure flag to turn assertion failures into
- segmentation faults.
- """
-
- def RunAndVerify(self, env_var_value, flag_value, expect_seg_fault):
- """Runs googletest-break-on-failure-unittest_ and verifies that it does
- (or does not) have a seg-fault.
-
- Args:
- env_var_value: value of the GTEST_BREAK_ON_FAILURE environment
- variable; None if the variable should be unset.
- flag_value: value of the --gtest_break_on_failure flag;
- None if the flag should not be present.
- expect_seg_fault: 1 if the program is expected to generate a seg-fault;
- 0 otherwise.
- """
-
- SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, env_var_value)
-
- if env_var_value is None:
- env_var_value_msg = ' is not set'
- else:
- env_var_value_msg = '=' + env_var_value
-
- if flag_value is None:
- flag = ''
- elif flag_value == '0':
- flag = '--%s=0' % BREAK_ON_FAILURE_FLAG
- else:
- flag = '--%s' % BREAK_ON_FAILURE_FLAG
-
- command = [EXE_PATH]
- if flag:
- command.append(flag)
-
- if expect_seg_fault:
- should_or_not = 'should'
- else:
- should_or_not = 'should not'
-
- has_seg_fault = Run(command)
-
- SetEnvVar(BREAK_ON_FAILURE_ENV_VAR, None)
-
- msg = ('when %s%s, an assertion failure in "%s" %s cause a seg-fault.' %
- (BREAK_ON_FAILURE_ENV_VAR, env_var_value_msg, ' '.join(command),
- should_or_not))
- self.assert_(has_seg_fault == expect_seg_fault, msg)
-
- def testDefaultBehavior(self):
- """Tests the behavior of the default mode."""
-
- self.RunAndVerify(env_var_value=None,
- flag_value=None,
- expect_seg_fault=0)
-
- def testEnvVar(self):
- """Tests using the GTEST_BREAK_ON_FAILURE environment variable."""
-
- self.RunAndVerify(env_var_value='0',
- flag_value=None,
- expect_seg_fault=0)
- self.RunAndVerify(env_var_value='1',
- flag_value=None,
- expect_seg_fault=1)
-
- def testFlag(self):
- """Tests using the --gtest_break_on_failure flag."""
-
- self.RunAndVerify(env_var_value=None,
- flag_value='0',
- expect_seg_fault=0)
- self.RunAndVerify(env_var_value=None,
- flag_value='1',
- expect_seg_fault=1)
-
- def testFlagOverridesEnvVar(self):
- """Tests that the flag overrides the environment variable."""
-
- self.RunAndVerify(env_var_value='0',
- flag_value='0',
- expect_seg_fault=0)
- self.RunAndVerify(env_var_value='0',
- flag_value='1',
- expect_seg_fault=1)
- self.RunAndVerify(env_var_value='1',
- flag_value='0',
- expect_seg_fault=0)
- self.RunAndVerify(env_var_value='1',
- flag_value='1',
- expect_seg_fault=1)
-
- def testBreakOnFailureOverridesThrowOnFailure(self):
- """Tests that gtest_break_on_failure overrides gtest_throw_on_failure."""
-
- SetEnvVar(THROW_ON_FAILURE_ENV_VAR, '1')
- try:
- self.RunAndVerify(env_var_value=None,
- flag_value='1',
- expect_seg_fault=1)
- finally:
- SetEnvVar(THROW_ON_FAILURE_ENV_VAR, None)
-
- if IS_WINDOWS:
- def testCatchExceptionsDoesNotInterfere(self):
- """Tests that gtest_catch_exceptions doesn't interfere."""
-
- SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, '1')
- try:
- self.RunAndVerify(env_var_value='1',
- flag_value='1',
- expect_seg_fault=1)
- finally:
- SetEnvVar(CATCH_EXCEPTIONS_ENV_VAR, None)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Unit test for Google Test's break-on-failure mode.
-//
-// A user can ask Google Test to seg-fault when an assertion fails, using
-// either the GTEST_BREAK_ON_FAILURE environment variable or the
-// --gtest_break_on_failure flag. This file is used for testing such
-// functionality.
-//
-// This program will be invoked from a Python unit test. It is
-// expected to fail. Don't run it directly.
-
-#include "gtest/gtest.h"
-
-#if GTEST_OS_WINDOWS
-# include <windows.h>
-# include <stdlib.h>
-#endif
-
-namespace {
-
-// A test that's expected to fail.
-TEST(Foo, Bar) {
- EXPECT_EQ(2, 3);
-}
-
-#if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
-// On Windows Mobile global exception handlers are not supported.
-LONG WINAPI ExitWithExceptionCode(
- struct _EXCEPTION_POINTERS* exception_pointers) {
- exit(exception_pointers->ExceptionRecord->ExceptionCode);
-}
-#endif
-
-} // namespace
-
-int main(int argc, char **argv) {
-#if GTEST_OS_WINDOWS
- // Suppresses display of the Windows error dialog upon encountering
- // a general protection fault (segment violation).
- SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS);
-
-# if GTEST_HAS_SEH && !GTEST_OS_WINDOWS_MOBILE
-
- // The default unhandled exception filter does not always exit
- // with the exception code as exit code - for example it exits with
- // 0 for EXCEPTION_ACCESS_VIOLATION and 1 for EXCEPTION_BREAKPOINT
- // if the application is compiled in debug mode. Thus we use our own
- // filter which always exits with the exception code for unhandled
- // exceptions.
- SetUnhandledExceptionFilter(ExitWithExceptionCode);
-
-# endif
-#endif // GTEST_OS_WINDOWS
- testing::InitGoogleTest(&argc, argv);
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2010 Google Inc. All Rights Reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests Google Test's exception catching behavior.
-
-This script invokes googletest-catch-exceptions-test_ and
-googletest-catch-exceptions-ex-test_ (programs written with
-Google Test) and verifies their output.
-"""
-
-import gtest_test_utils
-
-# Constants.
-FLAG_PREFIX = '--gtest_'
-LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
-NO_CATCH_EXCEPTIONS_FLAG = FLAG_PREFIX + 'catch_exceptions=0'
-FILTER_FLAG = FLAG_PREFIX + 'filter'
-
-# Path to the googletest-catch-exceptions-ex-test_ binary, compiled with
-# exceptions enabled.
-EX_EXE_PATH = gtest_test_utils.GetTestExecutablePath(
- 'googletest-catch-exceptions-ex-test_')
-
-# Path to the googletest-catch-exceptions-test_ binary, compiled with
-# exceptions disabled.
-EXE_PATH = gtest_test_utils.GetTestExecutablePath(
- 'googletest-catch-exceptions-no-ex-test_')
-
-environ = gtest_test_utils.environ
-SetEnvVar = gtest_test_utils.SetEnvVar
-
-# Tests in this file run a Google-Test-based test program and expect it
-# to terminate prematurely. Therefore they are incompatible with
-# the premature-exit-file protocol by design. Unset the
-# premature-exit filepath to prevent Google Test from creating
-# the file.
-SetEnvVar(gtest_test_utils.PREMATURE_EXIT_FILE_ENV_VAR, None)
-
-TEST_LIST = gtest_test_utils.Subprocess(
- [EXE_PATH, LIST_TESTS_FLAG], env=environ).output
-
-SUPPORTS_SEH_EXCEPTIONS = 'ThrowsSehException' in TEST_LIST
-
-if SUPPORTS_SEH_EXCEPTIONS:
- BINARY_OUTPUT = gtest_test_utils.Subprocess([EXE_PATH], env=environ).output
-
-EX_BINARY_OUTPUT = gtest_test_utils.Subprocess(
- [EX_EXE_PATH], env=environ).output
-
-
-# The tests.
-if SUPPORTS_SEH_EXCEPTIONS:
- # pylint:disable-msg=C6302
- class CatchSehExceptionsTest(gtest_test_utils.TestCase):
- """Tests exception-catching behavior."""
-
-
- def TestSehExceptions(self, test_output):
- self.assert_('SEH exception with code 0x2a thrown '
- 'in the test fixture\'s constructor'
- in test_output)
- self.assert_('SEH exception with code 0x2a thrown '
- 'in the test fixture\'s destructor'
- in test_output)
- self.assert_('SEH exception with code 0x2a thrown in SetUpTestSuite()'
- in test_output)
- self.assert_('SEH exception with code 0x2a thrown in TearDownTestSuite()'
- in test_output)
- self.assert_('SEH exception with code 0x2a thrown in SetUp()'
- in test_output)
- self.assert_('SEH exception with code 0x2a thrown in TearDown()'
- in test_output)
- self.assert_('SEH exception with code 0x2a thrown in the test body'
- in test_output)
-
- def testCatchesSehExceptionsWithCxxExceptionsEnabled(self):
- self.TestSehExceptions(EX_BINARY_OUTPUT)
-
- def testCatchesSehExceptionsWithCxxExceptionsDisabled(self):
- self.TestSehExceptions(BINARY_OUTPUT)
-
-
-class CatchCxxExceptionsTest(gtest_test_utils.TestCase):
- """Tests C++ exception-catching behavior.
-
- Tests in this test case verify that:
- * C++ exceptions are caught and logged as C++ (not SEH) exceptions
- * Exception thrown affect the remainder of the test work flow in the
- expected manner.
- """
-
- def testCatchesCxxExceptionsInFixtureConstructor(self):
- self.assertTrue(
- 'C++ exception with description '
- '"Standard C++ exception" thrown '
- 'in the test fixture\'s constructor' in EX_BINARY_OUTPUT,
- EX_BINARY_OUTPUT)
- self.assert_('unexpected' not in EX_BINARY_OUTPUT,
- 'This failure belongs in this test only if '
- '"CxxExceptionInConstructorTest" (no quotes) '
- 'appears on the same line as words "called unexpectedly"')
-
- if ('CxxExceptionInDestructorTest.ThrowsExceptionInDestructor' in
- EX_BINARY_OUTPUT):
-
- def testCatchesCxxExceptionsInFixtureDestructor(self):
- self.assertTrue(
- 'C++ exception with description '
- '"Standard C++ exception" thrown '
- 'in the test fixture\'s destructor' in EX_BINARY_OUTPUT,
- EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInDestructorTest::TearDownTestSuite() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
-
- def testCatchesCxxExceptionsInSetUpTestCase(self):
- self.assertTrue(
- 'C++ exception with description "Standard C++ exception"'
- ' thrown in SetUpTestSuite()' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInConstructorTest::TearDownTestSuite() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTestSuiteTest constructor '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTestSuiteTest destructor '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTestSuiteTest::SetUp() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTestSuiteTest::TearDown() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTestSuiteTest test body '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
-
- def testCatchesCxxExceptionsInTearDownTestCase(self):
- self.assertTrue(
- 'C++ exception with description "Standard C++ exception"'
- ' thrown in TearDownTestSuite()' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
-
- def testCatchesCxxExceptionsInSetUp(self):
- self.assertTrue(
- 'C++ exception with description "Standard C++ exception"'
- ' thrown in SetUp()' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTest::TearDownTestSuite() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTest destructor '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInSetUpTest::TearDown() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assert_('unexpected' not in EX_BINARY_OUTPUT,
- 'This failure belongs in this test only if '
- '"CxxExceptionInSetUpTest" (no quotes) '
- 'appears on the same line as words "called unexpectedly"')
-
- def testCatchesCxxExceptionsInTearDown(self):
- self.assertTrue(
- 'C++ exception with description "Standard C++ exception"'
- ' thrown in TearDown()' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInTearDownTest::TearDownTestSuite() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInTearDownTest destructor '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
-
- def testCatchesCxxExceptionsInTestBody(self):
- self.assertTrue(
- 'C++ exception with description "Standard C++ exception"'
- ' thrown in the test body' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInTestBodyTest::TearDownTestSuite() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInTestBodyTest destructor '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
- self.assertTrue(
- 'CxxExceptionInTestBodyTest::TearDown() '
- 'called as expected.' in EX_BINARY_OUTPUT, EX_BINARY_OUTPUT)
-
- def testCatchesNonStdCxxExceptions(self):
- self.assertTrue(
- 'Unknown C++ exception thrown in the test body' in EX_BINARY_OUTPUT,
- EX_BINARY_OUTPUT)
-
- def testUnhandledCxxExceptionsAbortTheProgram(self):
- # Filters out SEH exception tests on Windows. Unhandled SEH exceptions
- # cause tests to show pop-up windows there.
- FITLER_OUT_SEH_TESTS_FLAG = FILTER_FLAG + '=-*Seh*'
- # By default, Google Test doesn't catch the exceptions.
- uncaught_exceptions_ex_binary_output = gtest_test_utils.Subprocess(
- [EX_EXE_PATH,
- NO_CATCH_EXCEPTIONS_FLAG,
- FITLER_OUT_SEH_TESTS_FLAG],
- env=environ).output
-
- self.assert_('Unhandled C++ exception terminating the program'
- in uncaught_exceptions_ex_binary_output)
- self.assert_('unexpected' not in uncaught_exceptions_ex_binary_output)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2010, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for Google Test itself. Tests in this file throw C++ or SEH
-// exceptions, and the output is verified by
-// googletest-catch-exceptions-test.py.
-
-#include <stdio.h> // NOLINT
-#include <stdlib.h> // For exit().
-
-#include "gtest/gtest.h"
-
-#if GTEST_HAS_SEH
-# include <windows.h>
-#endif
-
-#if GTEST_HAS_EXCEPTIONS
-# include <exception> // For set_terminate().
-# include <stdexcept>
-#endif
-
-using testing::Test;
-
-#if GTEST_HAS_SEH
-
-class SehExceptionInConstructorTest : public Test {
- public:
- SehExceptionInConstructorTest() { RaiseException(42, 0, 0, NULL); }
-};
-
-TEST_F(SehExceptionInConstructorTest, ThrowsExceptionInConstructor) {}
-
-class SehExceptionInDestructorTest : public Test {
- public:
- ~SehExceptionInDestructorTest() { RaiseException(42, 0, 0, NULL); }
-};
-
-TEST_F(SehExceptionInDestructorTest, ThrowsExceptionInDestructor) {}
-
-class SehExceptionInSetUpTestSuiteTest : public Test {
- public:
- static void SetUpTestSuite() { RaiseException(42, 0, 0, NULL); }
-};
-
-TEST_F(SehExceptionInSetUpTestSuiteTest, ThrowsExceptionInSetUpTestSuite) {}
-
-class SehExceptionInTearDownTestSuiteTest : public Test {
- public:
- static void TearDownTestSuite() { RaiseException(42, 0, 0, NULL); }
-};
-
-TEST_F(SehExceptionInTearDownTestSuiteTest,
- ThrowsExceptionInTearDownTestSuite) {}
-
-class SehExceptionInSetUpTest : public Test {
- protected:
- virtual void SetUp() { RaiseException(42, 0, 0, NULL); }
-};
-
-TEST_F(SehExceptionInSetUpTest, ThrowsExceptionInSetUp) {}
-
-class SehExceptionInTearDownTest : public Test {
- protected:
- virtual void TearDown() { RaiseException(42, 0, 0, NULL); }
-};
-
-TEST_F(SehExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
-
-TEST(SehExceptionTest, ThrowsSehException) {
- RaiseException(42, 0, 0, NULL);
-}
-
-#endif // GTEST_HAS_SEH
-
-#if GTEST_HAS_EXCEPTIONS
-
-class CxxExceptionInConstructorTest : public Test {
- public:
- CxxExceptionInConstructorTest() {
- // Without this macro VC++ complains about unreachable code at the end of
- // the constructor.
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(
- throw std::runtime_error("Standard C++ exception"));
- }
-
- static void TearDownTestSuite() {
- printf("%s",
- "CxxExceptionInConstructorTest::TearDownTestSuite() "
- "called as expected.\n");
- }
-
- protected:
- ~CxxExceptionInConstructorTest() override {
- ADD_FAILURE() << "CxxExceptionInConstructorTest destructor "
- << "called unexpectedly.";
- }
-
- void SetUp() override {
- ADD_FAILURE() << "CxxExceptionInConstructorTest::SetUp() "
- << "called unexpectedly.";
- }
-
- void TearDown() override {
- ADD_FAILURE() << "CxxExceptionInConstructorTest::TearDown() "
- << "called unexpectedly.";
- }
-};
-
-TEST_F(CxxExceptionInConstructorTest, ThrowsExceptionInConstructor) {
- ADD_FAILURE() << "CxxExceptionInConstructorTest test body "
- << "called unexpectedly.";
-}
-
-class CxxExceptionInSetUpTestSuiteTest : public Test {
- public:
- CxxExceptionInSetUpTestSuiteTest() {
- printf("%s",
- "CxxExceptionInSetUpTestSuiteTest constructor "
- "called as expected.\n");
- }
-
- static void SetUpTestSuite() {
- throw std::runtime_error("Standard C++ exception");
- }
-
- static void TearDownTestSuite() {
- printf("%s",
- "CxxExceptionInSetUpTestSuiteTest::TearDownTestSuite() "
- "called as expected.\n");
- }
-
- protected:
- ~CxxExceptionInSetUpTestSuiteTest() override {
- printf("%s",
- "CxxExceptionInSetUpTestSuiteTest destructor "
- "called as expected.\n");
- }
-
- void SetUp() override {
- printf("%s",
- "CxxExceptionInSetUpTestSuiteTest::SetUp() "
- "called as expected.\n");
- }
-
- void TearDown() override {
- printf("%s",
- "CxxExceptionInSetUpTestSuiteTest::TearDown() "
- "called as expected.\n");
- }
-};
-
-TEST_F(CxxExceptionInSetUpTestSuiteTest, ThrowsExceptionInSetUpTestSuite) {
- printf("%s",
- "CxxExceptionInSetUpTestSuiteTest test body "
- "called as expected.\n");
-}
-
-class CxxExceptionInTearDownTestSuiteTest : public Test {
- public:
- static void TearDownTestSuite() {
- throw std::runtime_error("Standard C++ exception");
- }
-};
-
-TEST_F(CxxExceptionInTearDownTestSuiteTest,
- ThrowsExceptionInTearDownTestSuite) {}
-
-class CxxExceptionInSetUpTest : public Test {
- public:
- static void TearDownTestSuite() {
- printf("%s",
- "CxxExceptionInSetUpTest::TearDownTestSuite() "
- "called as expected.\n");
- }
-
- protected:
- ~CxxExceptionInSetUpTest() override {
- printf("%s",
- "CxxExceptionInSetUpTest destructor "
- "called as expected.\n");
- }
-
- void SetUp() override { throw std::runtime_error("Standard C++ exception"); }
-
- void TearDown() override {
- printf("%s",
- "CxxExceptionInSetUpTest::TearDown() "
- "called as expected.\n");
- }
-};
-
-TEST_F(CxxExceptionInSetUpTest, ThrowsExceptionInSetUp) {
- ADD_FAILURE() << "CxxExceptionInSetUpTest test body "
- << "called unexpectedly.";
-}
-
-class CxxExceptionInTearDownTest : public Test {
- public:
- static void TearDownTestSuite() {
- printf("%s",
- "CxxExceptionInTearDownTest::TearDownTestSuite() "
- "called as expected.\n");
- }
-
- protected:
- ~CxxExceptionInTearDownTest() override {
- printf("%s",
- "CxxExceptionInTearDownTest destructor "
- "called as expected.\n");
- }
-
- void TearDown() override {
- throw std::runtime_error("Standard C++ exception");
- }
-};
-
-TEST_F(CxxExceptionInTearDownTest, ThrowsExceptionInTearDown) {}
-
-class CxxExceptionInTestBodyTest : public Test {
- public:
- static void TearDownTestSuite() {
- printf("%s",
- "CxxExceptionInTestBodyTest::TearDownTestSuite() "
- "called as expected.\n");
- }
-
- protected:
- ~CxxExceptionInTestBodyTest() override {
- printf("%s",
- "CxxExceptionInTestBodyTest destructor "
- "called as expected.\n");
- }
-
- void TearDown() override {
- printf("%s",
- "CxxExceptionInTestBodyTest::TearDown() "
- "called as expected.\n");
- }
-};
-
-TEST_F(CxxExceptionInTestBodyTest, ThrowsStdCxxException) {
- throw std::runtime_error("Standard C++ exception");
-}
-
-TEST(CxxExceptionTest, ThrowsNonStdCxxException) {
- throw "C-string";
-}
-
-// This terminate handler aborts the program using exit() rather than abort().
-// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
-// ones.
-void TerminateHandler() {
- fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
- fflush(nullptr);
- exit(3);
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-int main(int argc, char** argv) {
-#if GTEST_HAS_EXCEPTIONS
- std::set_terminate(&TerminateHandler);
-#endif
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Verifies that Google Test correctly determines whether to use colors."""
-
-import os
-import gtest_test_utils
-
-IS_WINDOWS = os.name == 'nt'
-
-COLOR_ENV_VAR = 'GTEST_COLOR'
-COLOR_FLAG = 'gtest_color'
-COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-color-test_')
-
-
-def SetEnvVar(env_var, value):
- """Sets the env variable to 'value'; unsets it when 'value' is None."""
-
- if value is not None:
- os.environ[env_var] = value
- elif env_var in os.environ:
- del os.environ[env_var]
-
-
-def UsesColor(term, color_env_var, color_flag):
- """Runs googletest-color-test_ and returns its exit code."""
-
- SetEnvVar('TERM', term)
- SetEnvVar(COLOR_ENV_VAR, color_env_var)
-
- if color_flag is None:
- args = []
- else:
- args = ['--%s=%s' % (COLOR_FLAG, color_flag)]
- p = gtest_test_utils.Subprocess([COMMAND] + args)
- return not p.exited or p.exit_code
-
-
-class GTestColorTest(gtest_test_utils.TestCase):
- def testNoEnvVarNoFlag(self):
- """Tests the case when there's neither GTEST_COLOR nor --gtest_color."""
-
- if not IS_WINDOWS:
- self.assert_(not UsesColor('dumb', None, None))
- self.assert_(not UsesColor('emacs', None, None))
- self.assert_(not UsesColor('xterm-mono', None, None))
- self.assert_(not UsesColor('unknown', None, None))
- self.assert_(not UsesColor(None, None, None))
- self.assert_(UsesColor('linux', None, None))
- self.assert_(UsesColor('cygwin', None, None))
- self.assert_(UsesColor('xterm', None, None))
- self.assert_(UsesColor('xterm-color', None, None))
- self.assert_(UsesColor('xterm-256color', None, None))
-
- def testFlagOnly(self):
- """Tests the case when there's --gtest_color but not GTEST_COLOR."""
-
- self.assert_(not UsesColor('dumb', None, 'no'))
- self.assert_(not UsesColor('xterm-color', None, 'no'))
- if not IS_WINDOWS:
- self.assert_(not UsesColor('emacs', None, 'auto'))
- self.assert_(UsesColor('xterm', None, 'auto'))
- self.assert_(UsesColor('dumb', None, 'yes'))
- self.assert_(UsesColor('xterm', None, 'yes'))
-
- def testEnvVarOnly(self):
- """Tests the case when there's GTEST_COLOR but not --gtest_color."""
-
- self.assert_(not UsesColor('dumb', 'no', None))
- self.assert_(not UsesColor('xterm-color', 'no', None))
- if not IS_WINDOWS:
- self.assert_(not UsesColor('dumb', 'auto', None))
- self.assert_(UsesColor('xterm-color', 'auto', None))
- self.assert_(UsesColor('dumb', 'yes', None))
- self.assert_(UsesColor('xterm-color', 'yes', None))
-
- def testEnvVarAndFlag(self):
- """Tests the case when there are both GTEST_COLOR and --gtest_color."""
-
- self.assert_(not UsesColor('xterm-color', 'no', 'no'))
- self.assert_(UsesColor('dumb', 'no', 'yes'))
- self.assert_(UsesColor('xterm-color', 'no', 'auto'))
-
- def testAliasesOfYesAndNo(self):
- """Tests using aliases in specifying --gtest_color."""
-
- self.assert_(UsesColor('dumb', None, 'true'))
- self.assert_(UsesColor('dumb', None, 'YES'))
- self.assert_(UsesColor('dumb', None, 'T'))
- self.assert_(UsesColor('dumb', None, '1'))
-
- self.assert_(not UsesColor('xterm', None, 'f'))
- self.assert_(not UsesColor('xterm', None, 'false'))
- self.assert_(not UsesColor('xterm', None, '0'))
- self.assert_(not UsesColor('xterm', None, 'unknown'))
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// A helper program for testing how Google Test determines whether to use
-// colors in the output. It prints "YES" and returns 1 if Google Test
-// decides to use colors, and prints "NO" and returns 0 otherwise.
-
-#include <stdio.h>
-
-#include "gtest/gtest.h"
-#include "src/gtest-internal-inl.h"
-
-using testing::internal::ShouldUseColor;
-
-// The purpose of this is to ensure that the UnitTest singleton is
-// created before main() is entered, and thus that ShouldUseColor()
-// works the same way as in a real Google-Test-based test. We don't actual
-// run the TEST itself.
-TEST(GTestColorTest, Dummy) {
-}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
-
- if (ShouldUseColor(true)) {
- // Google Test decides to use colors in the output (assuming it
- // goes to a TTY).
- printf("YES\n");
- return 1;
- } else {
- // Google Test decides not to use colors in the output.
- printf("NO\n");
- return 0;
- }
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for death tests.
-
-#include "gtest/gtest-death-test.h"
-
-#include "gtest/gtest.h"
-#include "gtest/internal/gtest-filepath.h"
-
-using testing::internal::AlwaysFalse;
-using testing::internal::AlwaysTrue;
-
-#if GTEST_HAS_DEATH_TEST
-
-# if GTEST_OS_WINDOWS
-# include <fcntl.h> // For O_BINARY
-# include <direct.h> // For chdir().
-# include <io.h>
-# else
-# include <unistd.h>
-# include <sys/wait.h> // For waitpid.
-# endif // GTEST_OS_WINDOWS
-
-# include <limits.h>
-# include <signal.h>
-# include <stdio.h>
-
-# if GTEST_OS_LINUX
-# include <sys/time.h>
-# endif // GTEST_OS_LINUX
-
-# include "gtest/gtest-spi.h"
-# include "src/gtest-internal-inl.h"
-
-namespace posix = ::testing::internal::posix;
-
-using testing::ContainsRegex;
-using testing::Matcher;
-using testing::Message;
-using testing::internal::DeathTest;
-using testing::internal::DeathTestFactory;
-using testing::internal::FilePath;
-using testing::internal::GetLastErrnoDescription;
-using testing::internal::GetUnitTestImpl;
-using testing::internal::InDeathTestChild;
-using testing::internal::ParseNaturalNumber;
-
-namespace testing {
-namespace internal {
-
-// A helper class whose objects replace the death test factory for a
-// single UnitTest object during their lifetimes.
-class ReplaceDeathTestFactory {
- public:
- explicit ReplaceDeathTestFactory(DeathTestFactory* new_factory)
- : unit_test_impl_(GetUnitTestImpl()) {
- old_factory_ = unit_test_impl_->death_test_factory_.release();
- unit_test_impl_->death_test_factory_.reset(new_factory);
- }
-
- ~ReplaceDeathTestFactory() {
- unit_test_impl_->death_test_factory_.release();
- unit_test_impl_->death_test_factory_.reset(old_factory_);
- }
- private:
- // Prevents copying ReplaceDeathTestFactory objects.
- ReplaceDeathTestFactory(const ReplaceDeathTestFactory&);
- void operator=(const ReplaceDeathTestFactory&);
-
- UnitTestImpl* unit_test_impl_;
- DeathTestFactory* old_factory_;
-};
-
-} // namespace internal
-} // namespace testing
-
-namespace {
-
-void DieWithMessage(const ::std::string& message) {
- fprintf(stderr, "%s", message.c_str());
- fflush(stderr); // Make sure the text is printed before the process exits.
-
- // We call _exit() instead of exit(), as the former is a direct
- // system call and thus safer in the presence of threads. exit()
- // will invoke user-defined exit-hooks, which may do dangerous
- // things that conflict with death tests.
- //
- // Some compilers can recognize that _exit() never returns and issue the
- // 'unreachable code' warning for code following this function, unless
- // fooled by a fake condition.
- if (AlwaysTrue())
- _exit(1);
-}
-
-void DieInside(const ::std::string& function) {
- DieWithMessage("death inside " + function + "().");
-}
-
-// Tests that death tests work.
-
-class TestForDeathTest : public testing::Test {
- protected:
- TestForDeathTest() : original_dir_(FilePath::GetCurrentDir()) {}
-
- ~TestForDeathTest() override { posix::ChDir(original_dir_.c_str()); }
-
- // A static member function that's expected to die.
- static void StaticMemberFunction() { DieInside("StaticMemberFunction"); }
-
- // A method of the test fixture that may die.
- void MemberFunction() {
- if (should_die_)
- DieInside("MemberFunction");
- }
-
- // True if and only if MemberFunction() should die.
- bool should_die_;
- const FilePath original_dir_;
-};
-
-// A class with a member function that may die.
-class MayDie {
- public:
- explicit MayDie(bool should_die) : should_die_(should_die) {}
-
- // A member function that may die.
- void MemberFunction() const {
- if (should_die_)
- DieInside("MayDie::MemberFunction");
- }
-
- private:
- // True if and only if MemberFunction() should die.
- bool should_die_;
-};
-
-// A global function that's expected to die.
-void GlobalFunction() { DieInside("GlobalFunction"); }
-
-// A non-void function that's expected to die.
-int NonVoidFunction() {
- DieInside("NonVoidFunction");
- return 1;
-}
-
-// A unary function that may die.
-void DieIf(bool should_die) {
- if (should_die)
- DieInside("DieIf");
-}
-
-// A binary function that may die.
-bool DieIfLessThan(int x, int y) {
- if (x < y) {
- DieInside("DieIfLessThan");
- }
- return true;
-}
-
-// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
-void DeathTestSubroutine() {
- EXPECT_DEATH(GlobalFunction(), "death.*GlobalFunction");
- ASSERT_DEATH(GlobalFunction(), "death.*GlobalFunction");
-}
-
-// Death in dbg, not opt.
-int DieInDebugElse12(int* sideeffect) {
- if (sideeffect) *sideeffect = 12;
-
-# ifndef NDEBUG
-
- DieInside("DieInDebugElse12");
-
-# endif // NDEBUG
-
- return 12;
-}
-
-# if GTEST_OS_WINDOWS
-
-// Death in dbg due to Windows CRT assertion failure, not opt.
-int DieInCRTDebugElse12(int* sideeffect) {
- if (sideeffect) *sideeffect = 12;
-
- // Create an invalid fd by closing a valid one
- int fdpipe[2];
- EXPECT_EQ(_pipe(fdpipe, 256, O_BINARY), 0);
- EXPECT_EQ(_close(fdpipe[0]), 0);
- EXPECT_EQ(_close(fdpipe[1]), 0);
-
- // _dup() should crash in debug mode
- EXPECT_EQ(_dup(fdpipe[0]), -1);
-
- return 12;
-}
-
-#endif // GTEST_OS_WINDOWS
-
-# if GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-
-// Tests the ExitedWithCode predicate.
-TEST(ExitStatusPredicateTest, ExitedWithCode) {
- // On Windows, the process's exit code is the same as its exit status,
- // so the predicate just compares the its input with its parameter.
- EXPECT_TRUE(testing::ExitedWithCode(0)(0));
- EXPECT_TRUE(testing::ExitedWithCode(1)(1));
- EXPECT_TRUE(testing::ExitedWithCode(42)(42));
- EXPECT_FALSE(testing::ExitedWithCode(0)(1));
- EXPECT_FALSE(testing::ExitedWithCode(1)(0));
-}
-
-# else
-
-// Returns the exit status of a process that calls _exit(2) with a
-// given exit code. This is a helper function for the
-// ExitStatusPredicateTest test suite.
-static int NormalExitStatus(int exit_code) {
- pid_t child_pid = fork();
- if (child_pid == 0) {
- _exit(exit_code);
- }
- int status;
- waitpid(child_pid, &status, 0);
- return status;
-}
-
-// Returns the exit status of a process that raises a given signal.
-// If the signal does not cause the process to die, then it returns
-// instead the exit status of a process that exits normally with exit
-// code 1. This is a helper function for the ExitStatusPredicateTest
-// test suite.
-static int KilledExitStatus(int signum) {
- pid_t child_pid = fork();
- if (child_pid == 0) {
- raise(signum);
- _exit(1);
- }
- int status;
- waitpid(child_pid, &status, 0);
- return status;
-}
-
-// Tests the ExitedWithCode predicate.
-TEST(ExitStatusPredicateTest, ExitedWithCode) {
- const int status0 = NormalExitStatus(0);
- const int status1 = NormalExitStatus(1);
- const int status42 = NormalExitStatus(42);
- const testing::ExitedWithCode pred0(0);
- const testing::ExitedWithCode pred1(1);
- const testing::ExitedWithCode pred42(42);
- EXPECT_PRED1(pred0, status0);
- EXPECT_PRED1(pred1, status1);
- EXPECT_PRED1(pred42, status42);
- EXPECT_FALSE(pred0(status1));
- EXPECT_FALSE(pred42(status0));
- EXPECT_FALSE(pred1(status42));
-}
-
-// Tests the KilledBySignal predicate.
-TEST(ExitStatusPredicateTest, KilledBySignal) {
- const int status_segv = KilledExitStatus(SIGSEGV);
- const int status_kill = KilledExitStatus(SIGKILL);
- const testing::KilledBySignal pred_segv(SIGSEGV);
- const testing::KilledBySignal pred_kill(SIGKILL);
- EXPECT_PRED1(pred_segv, status_segv);
- EXPECT_PRED1(pred_kill, status_kill);
- EXPECT_FALSE(pred_segv(status_kill));
- EXPECT_FALSE(pred_kill(status_segv));
-}
-
-# endif // GTEST_OS_WINDOWS || GTEST_OS_FUCHSIA
-
-// Tests that the death test macros expand to code which may or may not
-// be followed by operator<<, and that in either case the complete text
-// comprises only a single C++ statement.
-TEST_F(TestForDeathTest, SingleStatement) {
- if (AlwaysFalse())
- // This would fail if executed; this is a compilation test only
- ASSERT_DEATH(return, "");
-
- if (AlwaysTrue())
- EXPECT_DEATH(_exit(1), "");
- else
- // This empty "else" branch is meant to ensure that EXPECT_DEATH
- // doesn't expand into an "if" statement without an "else"
- ;
-
- if (AlwaysFalse())
- ASSERT_DEATH(return, "") << "did not die";
-
- if (AlwaysFalse())
- ;
- else
- EXPECT_DEATH(_exit(1), "") << 1 << 2 << 3;
-}
-
-# if GTEST_USES_PCRE
-
-void DieWithEmbeddedNul() {
- fprintf(stderr, "Hello%cmy null world.\n", '\0');
- fflush(stderr);
- _exit(1);
-}
-
-// Tests that EXPECT_DEATH and ASSERT_DEATH work when the error
-// message has a NUL character in it.
-TEST_F(TestForDeathTest, EmbeddedNulInMessage) {
- EXPECT_DEATH(DieWithEmbeddedNul(), "my null world");
- ASSERT_DEATH(DieWithEmbeddedNul(), "my null world");
-}
-
-# endif // GTEST_USES_PCRE
-
-// Tests that death test macros expand to code which interacts well with switch
-// statements.
-TEST_F(TestForDeathTest, SwitchStatement) {
- // Microsoft compiler usually complains about switch statements without
- // case labels. We suppress that warning for this test.
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
-
- switch (0)
- default:
- ASSERT_DEATH(_exit(1), "") << "exit in default switch handler";
-
- switch (0)
- case 0:
- EXPECT_DEATH(_exit(1), "") << "exit in switch case";
-
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-}
-
-// Tests that a static member function can be used in a "fast" style
-// death test.
-TEST_F(TestForDeathTest, StaticMemberFunctionFastStyle) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
-}
-
-// Tests that a method of the test fixture can be used in a "fast"
-// style death test.
-TEST_F(TestForDeathTest, MemberFunctionFastStyle) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- should_die_ = true;
- EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
-}
-
-void ChangeToRootDir() { posix::ChDir(GTEST_PATH_SEP_); }
-
-// Tests that death tests work even if the current directory has been
-// changed.
-TEST_F(TestForDeathTest, FastDeathTestInChangedDir) {
- testing::GTEST_FLAG(death_test_style) = "fast";
-
- ChangeToRootDir();
- EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
-
- ChangeToRootDir();
- ASSERT_DEATH(_exit(1), "");
-}
-
-# if GTEST_OS_LINUX
-void SigprofAction(int, siginfo_t*, void*) { /* no op */ }
-
-// Sets SIGPROF action and ITIMER_PROF timer (interval: 1ms).
-void SetSigprofActionAndTimer() {
- struct itimerval timer;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 1;
- timer.it_value = timer.it_interval;
- ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, nullptr));
- struct sigaction signal_action;
- memset(&signal_action, 0, sizeof(signal_action));
- sigemptyset(&signal_action.sa_mask);
- signal_action.sa_sigaction = SigprofAction;
- signal_action.sa_flags = SA_RESTART | SA_SIGINFO;
- ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, nullptr));
-}
-
-// Disables ITIMER_PROF timer and ignores SIGPROF signal.
-void DisableSigprofActionAndTimer(struct sigaction* old_signal_action) {
- struct itimerval timer;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 0;
- timer.it_value = timer.it_interval;
- ASSERT_EQ(0, setitimer(ITIMER_PROF, &timer, nullptr));
- struct sigaction signal_action;
- memset(&signal_action, 0, sizeof(signal_action));
- sigemptyset(&signal_action.sa_mask);
- signal_action.sa_handler = SIG_IGN;
- ASSERT_EQ(0, sigaction(SIGPROF, &signal_action, old_signal_action));
-}
-
-// Tests that death tests work when SIGPROF handler and timer are set.
-TEST_F(TestForDeathTest, FastSigprofActionSet) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- SetSigprofActionAndTimer();
- EXPECT_DEATH(_exit(1), "");
- struct sigaction old_signal_action;
- DisableSigprofActionAndTimer(&old_signal_action);
- EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
-}
-
-TEST_F(TestForDeathTest, ThreadSafeSigprofActionSet) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- SetSigprofActionAndTimer();
- EXPECT_DEATH(_exit(1), "");
- struct sigaction old_signal_action;
- DisableSigprofActionAndTimer(&old_signal_action);
- EXPECT_TRUE(old_signal_action.sa_sigaction == SigprofAction);
-}
-# endif // GTEST_OS_LINUX
-
-// Repeats a representative sample of death tests in the "threadsafe" style:
-
-TEST_F(TestForDeathTest, StaticMemberFunctionThreadsafeStyle) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- ASSERT_DEATH(StaticMemberFunction(), "death.*StaticMember");
-}
-
-TEST_F(TestForDeathTest, MemberFunctionThreadsafeStyle) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- should_die_ = true;
- EXPECT_DEATH(MemberFunction(), "inside.*MemberFunction");
-}
-
-TEST_F(TestForDeathTest, ThreadsafeDeathTestInLoop) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
-
- for (int i = 0; i < 3; ++i)
- EXPECT_EXIT(_exit(i), testing::ExitedWithCode(i), "") << ": i = " << i;
-}
-
-TEST_F(TestForDeathTest, ThreadsafeDeathTestInChangedDir) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
-
- ChangeToRootDir();
- EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
-
- ChangeToRootDir();
- ASSERT_DEATH(_exit(1), "");
-}
-
-TEST_F(TestForDeathTest, MixedStyles) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- EXPECT_DEATH(_exit(1), "");
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_DEATH(_exit(1), "");
-}
-
-# if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
-
-bool pthread_flag;
-
-void SetPthreadFlag() {
- pthread_flag = true;
-}
-
-TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
- if (!testing::GTEST_FLAG(death_test_use_fork)) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- pthread_flag = false;
- ASSERT_EQ(0, pthread_atfork(&SetPthreadFlag, nullptr, nullptr));
- ASSERT_DEATH(_exit(1), "");
- ASSERT_FALSE(pthread_flag);
- }
-}
-
-# endif // GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
-
-// Tests that a method of another class can be used in a death test.
-TEST_F(TestForDeathTest, MethodOfAnotherClass) {
- const MayDie x(true);
- ASSERT_DEATH(x.MemberFunction(), "MayDie\\:\\:MemberFunction");
-}
-
-// Tests that a global function can be used in a death test.
-TEST_F(TestForDeathTest, GlobalFunction) {
- EXPECT_DEATH(GlobalFunction(), "GlobalFunction");
-}
-
-// Tests that any value convertible to an RE works as a second
-// argument to EXPECT_DEATH.
-TEST_F(TestForDeathTest, AcceptsAnythingConvertibleToRE) {
- static const char regex_c_str[] = "GlobalFunction";
- EXPECT_DEATH(GlobalFunction(), regex_c_str);
-
- const testing::internal::RE regex(regex_c_str);
- EXPECT_DEATH(GlobalFunction(), regex);
-
-# if !GTEST_USES_PCRE
-
- const ::std::string regex_std_str(regex_c_str);
- EXPECT_DEATH(GlobalFunction(), regex_std_str);
-
- // This one is tricky; a temporary pointer into another temporary. Reference
- // lifetime extension of the pointer is not sufficient.
- EXPECT_DEATH(GlobalFunction(), ::std::string(regex_c_str).c_str());
-
-# endif // !GTEST_USES_PCRE
-}
-
-// Tests that a non-void function can be used in a death test.
-TEST_F(TestForDeathTest, NonVoidFunction) {
- ASSERT_DEATH(NonVoidFunction(), "NonVoidFunction");
-}
-
-// Tests that functions that take parameter(s) can be used in a death test.
-TEST_F(TestForDeathTest, FunctionWithParameter) {
- EXPECT_DEATH(DieIf(true), "DieIf\\(\\)");
- EXPECT_DEATH(DieIfLessThan(2, 3), "DieIfLessThan");
-}
-
-// Tests that ASSERT_DEATH can be used outside a TEST, TEST_F, or test fixture.
-TEST_F(TestForDeathTest, OutsideFixture) {
- DeathTestSubroutine();
-}
-
-// Tests that death tests can be done inside a loop.
-TEST_F(TestForDeathTest, InsideLoop) {
- for (int i = 0; i < 5; i++) {
- EXPECT_DEATH(DieIfLessThan(-1, i), "DieIfLessThan") << "where i == " << i;
- }
-}
-
-// Tests that a compound statement can be used in a death test.
-TEST_F(TestForDeathTest, CompoundStatement) {
- EXPECT_DEATH({ // NOLINT
- const int x = 2;
- const int y = x + 1;
- DieIfLessThan(x, y);
- },
- "DieIfLessThan");
-}
-
-// Tests that code that doesn't die causes a death test to fail.
-TEST_F(TestForDeathTest, DoesNotDie) {
- EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieIf(false), "DieIf"),
- "failed to die");
-}
-
-// Tests that a death test fails when the error message isn't expected.
-TEST_F(TestForDeathTest, ErrorMessageMismatch) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_DEATH(DieIf(true), "DieIfLessThan") << "End of death test message.";
- }, "died but not with expected error");
-}
-
-// On exit, *aborted will be true if and only if the EXPECT_DEATH()
-// statement aborted the function.
-void ExpectDeathTestHelper(bool* aborted) {
- *aborted = true;
- EXPECT_DEATH(DieIf(false), "DieIf"); // This assertion should fail.
- *aborted = false;
-}
-
-// Tests that EXPECT_DEATH doesn't abort the test on failure.
-TEST_F(TestForDeathTest, EXPECT_DEATH) {
- bool aborted = true;
- EXPECT_NONFATAL_FAILURE(ExpectDeathTestHelper(&aborted),
- "failed to die");
- EXPECT_FALSE(aborted);
-}
-
-// Tests that ASSERT_DEATH does abort the test on failure.
-TEST_F(TestForDeathTest, ASSERT_DEATH) {
- static bool aborted;
- EXPECT_FATAL_FAILURE({ // NOLINT
- aborted = true;
- ASSERT_DEATH(DieIf(false), "DieIf"); // This assertion should fail.
- aborted = false;
- }, "failed to die");
- EXPECT_TRUE(aborted);
-}
-
-// Tests that EXPECT_DEATH evaluates the arguments exactly once.
-TEST_F(TestForDeathTest, SingleEvaluation) {
- int x = 3;
- EXPECT_DEATH(DieIf((++x) == 4), "DieIf");
-
- const char* regex = "DieIf";
- const char* regex_save = regex;
- EXPECT_DEATH(DieIfLessThan(3, 4), regex++);
- EXPECT_EQ(regex_save + 1, regex);
-}
-
-// Tests that run-away death tests are reported as failures.
-TEST_F(TestForDeathTest, RunawayIsFailure) {
- EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(static_cast<void>(0), "Foo"),
- "failed to die.");
-}
-
-// Tests that death tests report executing 'return' in the statement as
-// failure.
-TEST_F(TestForDeathTest, ReturnIsFailure) {
- EXPECT_FATAL_FAILURE(ASSERT_DEATH(return, "Bar"),
- "illegal return in test statement.");
-}
-
-// Tests that EXPECT_DEBUG_DEATH works as expected, that is, you can stream a
-// message to it, and in debug mode it:
-// 1. Asserts on death.
-// 2. Has no side effect.
-//
-// And in opt mode, it:
-// 1. Has side effects but does not assert.
-TEST_F(TestForDeathTest, TestExpectDebugDeath) {
- int sideeffect = 0;
-
- // Put the regex in a local variable to make sure we don't get an "unused"
- // warning in opt mode.
- const char* regex = "death.*DieInDebugElse12";
-
- EXPECT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), regex)
- << "Must accept a streamed message";
-
-# ifdef NDEBUG
-
- // Checks that the assignment occurs in opt mode (sideeffect).
- EXPECT_EQ(12, sideeffect);
-
-# else
-
- // Checks that the assignment does not occur in dbg mode (no sideeffect).
- EXPECT_EQ(0, sideeffect);
-
-# endif
-}
-
-# if GTEST_OS_WINDOWS
-
-// Tests that EXPECT_DEBUG_DEATH works as expected when in debug mode
-// the Windows CRT crashes the process with an assertion failure.
-// 1. Asserts on death.
-// 2. Has no side effect (doesn't pop up a window or wait for user input).
-//
-// And in opt mode, it:
-// 1. Has side effects but does not assert.
-TEST_F(TestForDeathTest, CRTDebugDeath) {
- int sideeffect = 0;
-
- // Put the regex in a local variable to make sure we don't get an "unused"
- // warning in opt mode.
- const char* regex = "dup.* : Assertion failed";
-
- EXPECT_DEBUG_DEATH(DieInCRTDebugElse12(&sideeffect), regex)
- << "Must accept a streamed message";
-
-# ifdef NDEBUG
-
- // Checks that the assignment occurs in opt mode (sideeffect).
- EXPECT_EQ(12, sideeffect);
-
-# else
-
- // Checks that the assignment does not occur in dbg mode (no sideeffect).
- EXPECT_EQ(0, sideeffect);
-
-# endif
-}
-
-# endif // GTEST_OS_WINDOWS
-
-// Tests that ASSERT_DEBUG_DEATH works as expected, that is, you can stream a
-// message to it, and in debug mode it:
-// 1. Asserts on death.
-// 2. Has no side effect.
-//
-// And in opt mode, it:
-// 1. Has side effects but does not assert.
-TEST_F(TestForDeathTest, TestAssertDebugDeath) {
- int sideeffect = 0;
-
- ASSERT_DEBUG_DEATH(DieInDebugElse12(&sideeffect), "death.*DieInDebugElse12")
- << "Must accept a streamed message";
-
-# ifdef NDEBUG
-
- // Checks that the assignment occurs in opt mode (sideeffect).
- EXPECT_EQ(12, sideeffect);
-
-# else
-
- // Checks that the assignment does not occur in dbg mode (no sideeffect).
- EXPECT_EQ(0, sideeffect);
-
-# endif
-}
-
-# ifndef NDEBUG
-
-void ExpectDebugDeathHelper(bool* aborted) {
- *aborted = true;
- EXPECT_DEBUG_DEATH(return, "") << "This is expected to fail.";
- *aborted = false;
-}
-
-# if GTEST_OS_WINDOWS
-TEST(PopUpDeathTest, DoesNotShowPopUpOnAbort) {
- printf("This test should be considered failing if it shows "
- "any pop-up dialogs.\n");
- fflush(stdout);
-
- EXPECT_DEATH({
- testing::GTEST_FLAG(catch_exceptions) = false;
- abort();
- }, "");
-}
-# endif // GTEST_OS_WINDOWS
-
-// Tests that EXPECT_DEBUG_DEATH in debug mode does not abort
-// the function.
-TEST_F(TestForDeathTest, ExpectDebugDeathDoesNotAbort) {
- bool aborted = true;
- EXPECT_NONFATAL_FAILURE(ExpectDebugDeathHelper(&aborted), "");
- EXPECT_FALSE(aborted);
-}
-
-void AssertDebugDeathHelper(bool* aborted) {
- *aborted = true;
- GTEST_LOG_(INFO) << "Before ASSERT_DEBUG_DEATH";
- ASSERT_DEBUG_DEATH(GTEST_LOG_(INFO) << "In ASSERT_DEBUG_DEATH"; return, "")
- << "This is expected to fail.";
- GTEST_LOG_(INFO) << "After ASSERT_DEBUG_DEATH";
- *aborted = false;
-}
-
-// Tests that ASSERT_DEBUG_DEATH in debug mode aborts the function on
-// failure.
-TEST_F(TestForDeathTest, AssertDebugDeathAborts) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts2) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts3) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts4) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts5) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts6) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts7) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts8) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts9) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-TEST_F(TestForDeathTest, AssertDebugDeathAborts10) {
- static bool aborted;
- aborted = false;
- EXPECT_FATAL_FAILURE(AssertDebugDeathHelper(&aborted), "");
- EXPECT_TRUE(aborted);
-}
-
-# endif // _NDEBUG
-
-// Tests the *_EXIT family of macros, using a variety of predicates.
-static void TestExitMacros() {
- EXPECT_EXIT(_exit(1), testing::ExitedWithCode(1), "");
- ASSERT_EXIT(_exit(42), testing::ExitedWithCode(42), "");
-
-# if GTEST_OS_WINDOWS
-
- // Of all signals effects on the process exit code, only those of SIGABRT
- // are documented on Windows.
- // See https://msdn.microsoft.com/en-us/query-bi/m/dwwzkt4c.
- EXPECT_EXIT(raise(SIGABRT), testing::ExitedWithCode(3), "") << "b_ar";
-
-# elif !GTEST_OS_FUCHSIA
-
- // Fuchsia has no unix signals.
- EXPECT_EXIT(raise(SIGKILL), testing::KilledBySignal(SIGKILL), "") << "foo";
- ASSERT_EXIT(raise(SIGUSR2), testing::KilledBySignal(SIGUSR2), "") << "bar";
-
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_EXIT(_exit(0), testing::KilledBySignal(SIGSEGV), "")
- << "This failure is expected, too.";
- }, "This failure is expected, too.");
-
-# endif // GTEST_OS_WINDOWS
-
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_EXIT(raise(SIGSEGV), testing::ExitedWithCode(0), "")
- << "This failure is expected.";
- }, "This failure is expected.");
-}
-
-TEST_F(TestForDeathTest, ExitMacros) {
- TestExitMacros();
-}
-
-TEST_F(TestForDeathTest, ExitMacrosUsingFork) {
- testing::GTEST_FLAG(death_test_use_fork) = true;
- TestExitMacros();
-}
-
-TEST_F(TestForDeathTest, InvalidStyle) {
- testing::GTEST_FLAG(death_test_style) = "rococo";
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_DEATH(_exit(0), "") << "This failure is expected.";
- }, "This failure is expected.");
-}
-
-TEST_F(TestForDeathTest, DeathTestFailedOutput) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_NONFATAL_FAILURE(
- EXPECT_DEATH(DieWithMessage("death\n"),
- "expected message"),
- "Actual msg:\n"
- "[ DEATH ] death\n");
-}
-
-TEST_F(TestForDeathTest, DeathTestUnexpectedReturnOutput) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_NONFATAL_FAILURE(
- EXPECT_DEATH({
- fprintf(stderr, "returning\n");
- fflush(stderr);
- return;
- }, ""),
- " Result: illegal return in test statement.\n"
- " Error msg:\n"
- "[ DEATH ] returning\n");
-}
-
-TEST_F(TestForDeathTest, DeathTestBadExitCodeOutput) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_NONFATAL_FAILURE(
- EXPECT_EXIT(DieWithMessage("exiting with rc 1\n"),
- testing::ExitedWithCode(3),
- "expected message"),
- " Result: died but not with expected exit code:\n"
- " Exited with exit status 1\n"
- "Actual msg:\n"
- "[ DEATH ] exiting with rc 1\n");
-}
-
-TEST_F(TestForDeathTest, DeathTestMultiLineMatchFail) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_NONFATAL_FAILURE(
- EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
- "line 1\nxyz\nline 3\n"),
- "Actual msg:\n"
- "[ DEATH ] line 1\n"
- "[ DEATH ] line 2\n"
- "[ DEATH ] line 3\n");
-}
-
-TEST_F(TestForDeathTest, DeathTestMultiLineMatchPass) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_DEATH(DieWithMessage("line 1\nline 2\nline 3\n"),
- "line 1\nline 2\nline 3\n");
-}
-
-// A DeathTestFactory that returns MockDeathTests.
-class MockDeathTestFactory : public DeathTestFactory {
- public:
- MockDeathTestFactory();
- bool Create(const char* statement,
- testing::Matcher<const std::string&> matcher, const char* file,
- int line, DeathTest** test) override;
-
- // Sets the parameters for subsequent calls to Create.
- void SetParameters(bool create, DeathTest::TestRole role,
- int status, bool passed);
-
- // Accessors.
- int AssumeRoleCalls() const { return assume_role_calls_; }
- int WaitCalls() const { return wait_calls_; }
- size_t PassedCalls() const { return passed_args_.size(); }
- bool PassedArgument(int n) const {
- return passed_args_[static_cast<size_t>(n)];
- }
- size_t AbortCalls() const { return abort_args_.size(); }
- DeathTest::AbortReason AbortArgument(int n) const {
- return abort_args_[static_cast<size_t>(n)];
- }
- bool TestDeleted() const { return test_deleted_; }
-
- private:
- friend class MockDeathTest;
- // If true, Create will return a MockDeathTest; otherwise it returns
- // NULL.
- bool create_;
- // The value a MockDeathTest will return from its AssumeRole method.
- DeathTest::TestRole role_;
- // The value a MockDeathTest will return from its Wait method.
- int status_;
- // The value a MockDeathTest will return from its Passed method.
- bool passed_;
-
- // Number of times AssumeRole was called.
- int assume_role_calls_;
- // Number of times Wait was called.
- int wait_calls_;
- // The arguments to the calls to Passed since the last call to
- // SetParameters.
- std::vector<bool> passed_args_;
- // The arguments to the calls to Abort since the last call to
- // SetParameters.
- std::vector<DeathTest::AbortReason> abort_args_;
- // True if the last MockDeathTest returned by Create has been
- // deleted.
- bool test_deleted_;
-};
-
-
-// A DeathTest implementation useful in testing. It returns values set
-// at its creation from its various inherited DeathTest methods, and
-// reports calls to those methods to its parent MockDeathTestFactory
-// object.
-class MockDeathTest : public DeathTest {
- public:
- MockDeathTest(MockDeathTestFactory *parent,
- TestRole role, int status, bool passed) :
- parent_(parent), role_(role), status_(status), passed_(passed) {
- }
- ~MockDeathTest() override { parent_->test_deleted_ = true; }
- TestRole AssumeRole() override {
- ++parent_->assume_role_calls_;
- return role_;
- }
- int Wait() override {
- ++parent_->wait_calls_;
- return status_;
- }
- bool Passed(bool exit_status_ok) override {
- parent_->passed_args_.push_back(exit_status_ok);
- return passed_;
- }
- void Abort(AbortReason reason) override {
- parent_->abort_args_.push_back(reason);
- }
-
- private:
- MockDeathTestFactory* const parent_;
- const TestRole role_;
- const int status_;
- const bool passed_;
-};
-
-
-// MockDeathTestFactory constructor.
-MockDeathTestFactory::MockDeathTestFactory()
- : create_(true),
- role_(DeathTest::OVERSEE_TEST),
- status_(0),
- passed_(true),
- assume_role_calls_(0),
- wait_calls_(0),
- passed_args_(),
- abort_args_() {
-}
-
-
-// Sets the parameters for subsequent calls to Create.
-void MockDeathTestFactory::SetParameters(bool create,
- DeathTest::TestRole role,
- int status, bool passed) {
- create_ = create;
- role_ = role;
- status_ = status;
- passed_ = passed;
-
- assume_role_calls_ = 0;
- wait_calls_ = 0;
- passed_args_.clear();
- abort_args_.clear();
-}
-
-
-// Sets test to NULL (if create_ is false) or to the address of a new
-// MockDeathTest object with parameters taken from the last call
-// to SetParameters (if create_ is true). Always returns true.
-bool MockDeathTestFactory::Create(
- const char* /*statement*/, testing::Matcher<const std::string&> /*matcher*/,
- const char* /*file*/, int /*line*/, DeathTest** test) {
- test_deleted_ = false;
- if (create_) {
- *test = new MockDeathTest(this, role_, status_, passed_);
- } else {
- *test = nullptr;
- }
- return true;
-}
-
-// A test fixture for testing the logic of the GTEST_DEATH_TEST_ macro.
-// It installs a MockDeathTestFactory that is used for the duration
-// of the test case.
-class MacroLogicDeathTest : public testing::Test {
- protected:
- static testing::internal::ReplaceDeathTestFactory* replacer_;
- static MockDeathTestFactory* factory_;
-
- static void SetUpTestSuite() {
- factory_ = new MockDeathTestFactory;
- replacer_ = new testing::internal::ReplaceDeathTestFactory(factory_);
- }
-
- static void TearDownTestSuite() {
- delete replacer_;
- replacer_ = nullptr;
- delete factory_;
- factory_ = nullptr;
- }
-
- // Runs a death test that breaks the rules by returning. Such a death
- // test cannot be run directly from a test routine that uses a
- // MockDeathTest, or the remainder of the routine will not be executed.
- static void RunReturningDeathTest(bool* flag) {
- ASSERT_DEATH({ // NOLINT
- *flag = true;
- return;
- }, "");
- }
-};
-
-testing::internal::ReplaceDeathTestFactory* MacroLogicDeathTest::replacer_ =
- nullptr;
-MockDeathTestFactory* MacroLogicDeathTest::factory_ = nullptr;
-
-// Test that nothing happens when the factory doesn't return a DeathTest:
-TEST_F(MacroLogicDeathTest, NothingHappens) {
- bool flag = false;
- factory_->SetParameters(false, DeathTest::OVERSEE_TEST, 0, true);
- EXPECT_DEATH(flag = true, "");
- EXPECT_FALSE(flag);
- EXPECT_EQ(0, factory_->AssumeRoleCalls());
- EXPECT_EQ(0, factory_->WaitCalls());
- EXPECT_EQ(0U, factory_->PassedCalls());
- EXPECT_EQ(0U, factory_->AbortCalls());
- EXPECT_FALSE(factory_->TestDeleted());
-}
-
-// Test that the parent process doesn't run the death test code,
-// and that the Passed method returns false when the (simulated)
-// child process exits with status 0:
-TEST_F(MacroLogicDeathTest, ChildExitsSuccessfully) {
- bool flag = false;
- factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 0, true);
- EXPECT_DEATH(flag = true, "");
- EXPECT_FALSE(flag);
- EXPECT_EQ(1, factory_->AssumeRoleCalls());
- EXPECT_EQ(1, factory_->WaitCalls());
- ASSERT_EQ(1U, factory_->PassedCalls());
- EXPECT_FALSE(factory_->PassedArgument(0));
- EXPECT_EQ(0U, factory_->AbortCalls());
- EXPECT_TRUE(factory_->TestDeleted());
-}
-
-// Tests that the Passed method was given the argument "true" when
-// the (simulated) child process exits with status 1:
-TEST_F(MacroLogicDeathTest, ChildExitsUnsuccessfully) {
- bool flag = false;
- factory_->SetParameters(true, DeathTest::OVERSEE_TEST, 1, true);
- EXPECT_DEATH(flag = true, "");
- EXPECT_FALSE(flag);
- EXPECT_EQ(1, factory_->AssumeRoleCalls());
- EXPECT_EQ(1, factory_->WaitCalls());
- ASSERT_EQ(1U, factory_->PassedCalls());
- EXPECT_TRUE(factory_->PassedArgument(0));
- EXPECT_EQ(0U, factory_->AbortCalls());
- EXPECT_TRUE(factory_->TestDeleted());
-}
-
-// Tests that the (simulated) child process executes the death test
-// code, and is aborted with the correct AbortReason if it
-// executes a return statement.
-TEST_F(MacroLogicDeathTest, ChildPerformsReturn) {
- bool flag = false;
- factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
- RunReturningDeathTest(&flag);
- EXPECT_TRUE(flag);
- EXPECT_EQ(1, factory_->AssumeRoleCalls());
- EXPECT_EQ(0, factory_->WaitCalls());
- EXPECT_EQ(0U, factory_->PassedCalls());
- EXPECT_EQ(1U, factory_->AbortCalls());
- EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
- factory_->AbortArgument(0));
- EXPECT_TRUE(factory_->TestDeleted());
-}
-
-// Tests that the (simulated) child process is aborted with the
-// correct AbortReason if it does not die.
-TEST_F(MacroLogicDeathTest, ChildDoesNotDie) {
- bool flag = false;
- factory_->SetParameters(true, DeathTest::EXECUTE_TEST, 0, true);
- EXPECT_DEATH(flag = true, "");
- EXPECT_TRUE(flag);
- EXPECT_EQ(1, factory_->AssumeRoleCalls());
- EXPECT_EQ(0, factory_->WaitCalls());
- EXPECT_EQ(0U, factory_->PassedCalls());
- // This time there are two calls to Abort: one since the test didn't
- // die, and another from the ReturnSentinel when it's destroyed. The
- // sentinel normally isn't destroyed if a test doesn't die, since
- // _exit(2) is called in that case by ForkingDeathTest, but not by
- // our MockDeathTest.
- ASSERT_EQ(2U, factory_->AbortCalls());
- EXPECT_EQ(DeathTest::TEST_DID_NOT_DIE,
- factory_->AbortArgument(0));
- EXPECT_EQ(DeathTest::TEST_ENCOUNTERED_RETURN_STATEMENT,
- factory_->AbortArgument(1));
- EXPECT_TRUE(factory_->TestDeleted());
-}
-
-// Tests that a successful death test does not register a successful
-// test part.
-TEST(SuccessRegistrationDeathTest, NoSuccessPart) {
- EXPECT_DEATH(_exit(1), "");
- EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
-}
-
-TEST(StreamingAssertionsDeathTest, DeathTest) {
- EXPECT_DEATH(_exit(1), "") << "unexpected failure";
- ASSERT_DEATH(_exit(1), "") << "unexpected failure";
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_DEATH(_exit(0), "") << "expected failure";
- }, "expected failure");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_DEATH(_exit(0), "") << "expected failure";
- }, "expected failure");
-}
-
-// Tests that GetLastErrnoDescription returns an empty string when the
-// last error is 0 and non-empty string when it is non-zero.
-TEST(GetLastErrnoDescription, GetLastErrnoDescriptionWorks) {
- errno = ENOENT;
- EXPECT_STRNE("", GetLastErrnoDescription().c_str());
- errno = 0;
- EXPECT_STREQ("", GetLastErrnoDescription().c_str());
-}
-
-# if GTEST_OS_WINDOWS
-TEST(AutoHandleTest, AutoHandleWorks) {
- HANDLE handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
- ASSERT_NE(INVALID_HANDLE_VALUE, handle);
-
- // Tests that the AutoHandle is correctly initialized with a handle.
- testing::internal::AutoHandle auto_handle(handle);
- EXPECT_EQ(handle, auto_handle.Get());
-
- // Tests that Reset assigns INVALID_HANDLE_VALUE.
- // Note that this cannot verify whether the original handle is closed.
- auto_handle.Reset();
- EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle.Get());
-
- // Tests that Reset assigns the new handle.
- // Note that this cannot verify whether the original handle is closed.
- handle = ::CreateEvent(NULL, FALSE, FALSE, NULL);
- ASSERT_NE(INVALID_HANDLE_VALUE, handle);
- auto_handle.Reset(handle);
- EXPECT_EQ(handle, auto_handle.Get());
-
- // Tests that AutoHandle contains INVALID_HANDLE_VALUE by default.
- testing::internal::AutoHandle auto_handle2;
- EXPECT_EQ(INVALID_HANDLE_VALUE, auto_handle2.Get());
-}
-# endif // GTEST_OS_WINDOWS
-
-# if GTEST_OS_WINDOWS
-typedef unsigned __int64 BiggestParsable;
-typedef signed __int64 BiggestSignedParsable;
-# else
-typedef unsigned long long BiggestParsable;
-typedef signed long long BiggestSignedParsable;
-# endif // GTEST_OS_WINDOWS
-
-// We cannot use std::numeric_limits<T>::max() as it clashes with the
-// max() macro defined by <windows.h>.
-const BiggestParsable kBiggestParsableMax = ULLONG_MAX;
-const BiggestSignedParsable kBiggestSignedParsableMax = LLONG_MAX;
-
-TEST(ParseNaturalNumberTest, RejectsInvalidFormat) {
- BiggestParsable result = 0;
-
- // Rejects non-numbers.
- EXPECT_FALSE(ParseNaturalNumber("non-number string", &result));
-
- // Rejects numbers with whitespace prefix.
- EXPECT_FALSE(ParseNaturalNumber(" 123", &result));
-
- // Rejects negative numbers.
- EXPECT_FALSE(ParseNaturalNumber("-123", &result));
-
- // Rejects numbers starting with a plus sign.
- EXPECT_FALSE(ParseNaturalNumber("+123", &result));
- errno = 0;
-}
-
-TEST(ParseNaturalNumberTest, RejectsOverflownNumbers) {
- BiggestParsable result = 0;
-
- EXPECT_FALSE(ParseNaturalNumber("99999999999999999999999", &result));
-
- signed char char_result = 0;
- EXPECT_FALSE(ParseNaturalNumber("200", &char_result));
- errno = 0;
-}
-
-TEST(ParseNaturalNumberTest, AcceptsValidNumbers) {
- BiggestParsable result = 0;
-
- result = 0;
- ASSERT_TRUE(ParseNaturalNumber("123", &result));
- EXPECT_EQ(123U, result);
-
- // Check 0 as an edge case.
- result = 1;
- ASSERT_TRUE(ParseNaturalNumber("0", &result));
- EXPECT_EQ(0U, result);
-
- result = 1;
- ASSERT_TRUE(ParseNaturalNumber("00000", &result));
- EXPECT_EQ(0U, result);
-}
-
-TEST(ParseNaturalNumberTest, AcceptsTypeLimits) {
- Message msg;
- msg << kBiggestParsableMax;
-
- BiggestParsable result = 0;
- EXPECT_TRUE(ParseNaturalNumber(msg.GetString(), &result));
- EXPECT_EQ(kBiggestParsableMax, result);
-
- Message msg2;
- msg2 << kBiggestSignedParsableMax;
-
- BiggestSignedParsable signed_result = 0;
- EXPECT_TRUE(ParseNaturalNumber(msg2.GetString(), &signed_result));
- EXPECT_EQ(kBiggestSignedParsableMax, signed_result);
-
- Message msg3;
- msg3 << INT_MAX;
-
- int int_result = 0;
- EXPECT_TRUE(ParseNaturalNumber(msg3.GetString(), &int_result));
- EXPECT_EQ(INT_MAX, int_result);
-
- Message msg4;
- msg4 << UINT_MAX;
-
- unsigned int uint_result = 0;
- EXPECT_TRUE(ParseNaturalNumber(msg4.GetString(), &uint_result));
- EXPECT_EQ(UINT_MAX, uint_result);
-}
-
-TEST(ParseNaturalNumberTest, WorksForShorterIntegers) {
- short short_result = 0;
- ASSERT_TRUE(ParseNaturalNumber("123", &short_result));
- EXPECT_EQ(123, short_result);
-
- signed char char_result = 0;
- ASSERT_TRUE(ParseNaturalNumber("123", &char_result));
- EXPECT_EQ(123, char_result);
-}
-
-# if GTEST_OS_WINDOWS
-TEST(EnvironmentTest, HandleFitsIntoSizeT) {
- ASSERT_TRUE(sizeof(HANDLE) <= sizeof(size_t));
-}
-# endif // GTEST_OS_WINDOWS
-
-// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED trigger
-// failures when death tests are available on the system.
-TEST(ConditionalDeathMacrosDeathTest, ExpectsDeathWhenDeathTestsAvailable) {
- EXPECT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestExpectMacro"),
- "death inside CondDeathTestExpectMacro");
- ASSERT_DEATH_IF_SUPPORTED(DieInside("CondDeathTestAssertMacro"),
- "death inside CondDeathTestAssertMacro");
-
- // Empty statement will not crash, which must trigger a failure.
- EXPECT_NONFATAL_FAILURE(EXPECT_DEATH_IF_SUPPORTED(;, ""), "");
- EXPECT_FATAL_FAILURE(ASSERT_DEATH_IF_SUPPORTED(;, ""), "");
-}
-
-TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInFastStyle) {
- testing::GTEST_FLAG(death_test_style) = "fast";
- EXPECT_FALSE(InDeathTestChild());
- EXPECT_DEATH({
- fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
- fflush(stderr);
- _exit(1);
- }, "Inside");
-}
-
-TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInThreadSafeStyle) {
- testing::GTEST_FLAG(death_test_style) = "threadsafe";
- EXPECT_FALSE(InDeathTestChild());
- EXPECT_DEATH({
- fprintf(stderr, InDeathTestChild() ? "Inside" : "Outside");
- fflush(stderr);
- _exit(1);
- }, "Inside");
-}
-
-void DieWithMessage(const char* message) {
- fputs(message, stderr);
- fflush(stderr); // Make sure the text is printed before the process exits.
- _exit(1);
-}
-
-TEST(MatcherDeathTest, DoesNotBreakBareRegexMatching) {
- // googletest tests this, of course; here we ensure that including googlemock
- // has not broken it.
- EXPECT_DEATH(DieWithMessage("O, I die, Horatio."), "I d[aeiou]e");
-}
-
-TEST(MatcherDeathTest, MonomorphicMatcherMatches) {
- EXPECT_DEATH(DieWithMessage("Behind O, I am slain!"),
- Matcher<const std::string&>(ContainsRegex("I am slain")));
-}
-
-TEST(MatcherDeathTest, MonomorphicMatcherDoesNotMatch) {
- EXPECT_NONFATAL_FAILURE(
- EXPECT_DEATH(
- DieWithMessage("Behind O, I am slain!"),
- Matcher<const std::string&>(ContainsRegex("Ow, I am slain"))),
- "Expected: contains regular expression \"Ow, I am slain\"");
-}
-
-TEST(MatcherDeathTest, PolymorphicMatcherMatches) {
- EXPECT_DEATH(DieWithMessage("The rest is silence."),
- ContainsRegex("rest is silence"));
-}
-
-TEST(MatcherDeathTest, PolymorphicMatcherDoesNotMatch) {
- EXPECT_NONFATAL_FAILURE(
- EXPECT_DEATH(DieWithMessage("The rest is silence."),
- ContainsRegex("rest is science")),
- "Expected: contains regular expression \"rest is science\"");
-}
-
-} // namespace
-
-#else // !GTEST_HAS_DEATH_TEST follows
-
-namespace {
-
-using testing::internal::CaptureStderr;
-using testing::internal::GetCapturedStderr;
-
-// Tests that EXPECT_DEATH_IF_SUPPORTED/ASSERT_DEATH_IF_SUPPORTED are still
-// defined but do not trigger failures when death tests are not available on
-// the system.
-TEST(ConditionalDeathMacrosTest, WarnsWhenDeathTestsNotAvailable) {
- // Empty statement will not crash, but that should not trigger a failure
- // when death tests are not supported.
- CaptureStderr();
- EXPECT_DEATH_IF_SUPPORTED(;, "");
- std::string output = GetCapturedStderr();
- ASSERT_TRUE(NULL != strstr(output.c_str(),
- "Death tests are not supported on this platform"));
- ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
-
- // The streamed message should not be printed as there is no test failure.
- CaptureStderr();
- EXPECT_DEATH_IF_SUPPORTED(;, "") << "streamed message";
- output = GetCapturedStderr();
- ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
-
- CaptureStderr();
- ASSERT_DEATH_IF_SUPPORTED(;, ""); // NOLINT
- output = GetCapturedStderr();
- ASSERT_TRUE(NULL != strstr(output.c_str(),
- "Death tests are not supported on this platform"));
- ASSERT_TRUE(NULL != strstr(output.c_str(), ";"));
-
- CaptureStderr();
- ASSERT_DEATH_IF_SUPPORTED(;, "") << "streamed message"; // NOLINT
- output = GetCapturedStderr();
- ASSERT_TRUE(NULL == strstr(output.c_str(), "streamed message"));
-}
-
-void FuncWithAssert(int* n) {
- ASSERT_DEATH_IF_SUPPORTED(return;, "");
- (*n)++;
-}
-
-// Tests that ASSERT_DEATH_IF_SUPPORTED does not return from the current
-// function (as ASSERT_DEATH does) if death tests are not supported.
-TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
- int n = 0;
- FuncWithAssert(&n);
- EXPECT_EQ(1, n);
-}
-
-} // namespace
-
-#endif // !GTEST_HAS_DEATH_TEST
-
-namespace {
-
-// Tests that the death test macros expand to code which may or may not
-// be followed by operator<<, and that in either case the complete text
-// comprises only a single C++ statement.
-//
-// The syntax should work whether death tests are available or not.
-TEST(ConditionalDeathMacrosSyntaxDeathTest, SingleStatement) {
- if (AlwaysFalse())
- // This would fail if executed; this is a compilation test only
- ASSERT_DEATH_IF_SUPPORTED(return, "");
-
- if (AlwaysTrue())
- EXPECT_DEATH_IF_SUPPORTED(_exit(1), "");
- else
- // This empty "else" branch is meant to ensure that EXPECT_DEATH
- // doesn't expand into an "if" statement without an "else"
- ; // NOLINT
-
- if (AlwaysFalse())
- ASSERT_DEATH_IF_SUPPORTED(return, "") << "did not die";
-
- if (AlwaysFalse())
- ; // NOLINT
- else
- EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << 1 << 2 << 3;
-}
-
-// Tests that conditional death test macros expand to code which interacts
-// well with switch statements.
-TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
- // Microsoft compiler usually complains about switch statements without
- // case labels. We suppress that warning for this test.
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4065)
-
- switch (0)
- default:
- ASSERT_DEATH_IF_SUPPORTED(_exit(1), "")
- << "exit in default switch handler";
-
- switch (0)
- case 0:
- EXPECT_DEATH_IF_SUPPORTED(_exit(1), "") << "exit in switch case";
-
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-}
-
-// Tests that a test case whose name ends with "DeathTest" works fine
-// on Windows.
-TEST(NotADeathTest, Test) {
- SUCCEED();
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2010, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests that verify interaction of exceptions and death tests.
-
-#include "gtest/gtest-death-test.h"
-#include "gtest/gtest.h"
-
-#if GTEST_HAS_DEATH_TEST
-
-# if GTEST_HAS_SEH
-# include <windows.h> // For RaiseException().
-# endif
-
-# include "gtest/gtest-spi.h"
-
-# if GTEST_HAS_EXCEPTIONS
-
-# include <exception> // For std::exception.
-
-// Tests that death tests report thrown exceptions as failures and that the
-// exceptions do not escape death test macros.
-TEST(CxxExceptionDeathTest, ExceptionIsFailure) {
- try {
- EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw 1, ""), "threw an exception");
- } catch (...) { // NOLINT
- FAIL() << "An exception escaped a death test macro invocation "
- << "with catch_exceptions "
- << (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
- }
-}
-
-class TestException : public std::exception {
- public:
- const char* what() const throw() override { return "exceptional message"; }
-};
-
-TEST(CxxExceptionDeathTest, PrintsMessageForStdExceptions) {
- // Verifies that the exception message is quoted in the failure text.
- EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
- "exceptional message");
- // Verifies that the location is mentioned in the failure text.
- EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(throw TestException(), ""),
- __FILE__);
-}
-# endif // GTEST_HAS_EXCEPTIONS
-
-# if GTEST_HAS_SEH
-// Tests that enabling interception of SEH exceptions with the
-// catch_exceptions flag does not interfere with SEH exceptions being
-// treated as death by death tests.
-TEST(SehExceptionDeasTest, CatchExceptionsDoesNotInterfere) {
- EXPECT_DEATH(RaiseException(42, 0x0, 0, NULL), "")
- << "with catch_exceptions "
- << (testing::GTEST_FLAG(catch_exceptions) ? "enabled" : "disabled");
-}
-# endif
-
-#endif // GTEST_HAS_DEATH_TEST
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
- testing::GTEST_FLAG(catch_exceptions) = GTEST_ENABLE_CATCH_EXCEPTIONS_ != 0;
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Verifies that Google Test correctly parses environment variables."""
-
-import os
-import gtest_test_utils
-
-
-IS_WINDOWS = os.name == 'nt'
-IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
-
-COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-env-var-test_')
-
-environ = os.environ.copy()
-
-
-def AssertEq(expected, actual):
- if expected != actual:
- print('Expected: %s' % (expected,))
- print(' Actual: %s' % (actual,))
- raise AssertionError
-
-
-def SetEnvVar(env_var, value):
- """Sets the env variable to 'value'; unsets it when 'value' is None."""
-
- if value is not None:
- environ[env_var] = value
- elif env_var in environ:
- del environ[env_var]
-
-
-def GetFlag(flag):
- """Runs googletest-env-var-test_ and returns its output."""
-
- args = [COMMAND]
- if flag is not None:
- args += [flag]
- return gtest_test_utils.Subprocess(args, env=environ).output
-
-
-def TestFlag(flag, test_val, default_val):
- """Verifies that the given flag is affected by the corresponding env var."""
-
- env_var = 'GTEST_' + flag.upper()
- SetEnvVar(env_var, test_val)
- AssertEq(test_val, GetFlag(flag))
- SetEnvVar(env_var, None)
- AssertEq(default_val, GetFlag(flag))
-
-
-class GTestEnvVarTest(gtest_test_utils.TestCase):
-
- def testEnvVarAffectsFlag(self):
- """Tests that environment variable should affect the corresponding flag."""
-
- TestFlag('break_on_failure', '1', '0')
- TestFlag('color', 'yes', 'auto')
- TestFlag('filter', 'FooTest.Bar', '*')
- SetEnvVar('XML_OUTPUT_FILE', None) # For 'output' test
- TestFlag('output', 'xml:tmp/foo.xml', '')
- TestFlag('print_time', '0', '1')
- TestFlag('repeat', '999', '1')
- TestFlag('throw_on_failure', '1', '0')
- TestFlag('death_test_style', 'threadsafe', 'fast')
- TestFlag('catch_exceptions', '0', '1')
-
- if IS_LINUX:
- TestFlag('death_test_use_fork', '1', '0')
- TestFlag('stack_trace_depth', '0', '100')
-
-
- def testXmlOutputFile(self):
- """Tests that $XML_OUTPUT_FILE affects the output flag."""
-
- SetEnvVar('GTEST_OUTPUT', None)
- SetEnvVar('XML_OUTPUT_FILE', 'tmp/bar.xml')
- AssertEq('xml:tmp/bar.xml', GetFlag('output'))
-
- def testXmlOutputFileOverride(self):
- """Tests that $XML_OUTPUT_FILE is overridden by $GTEST_OUTPUT."""
-
- SetEnvVar('GTEST_OUTPUT', 'xml:tmp/foo.xml')
- SetEnvVar('XML_OUTPUT_FILE', 'tmp/bar.xml')
- AssertEq('xml:tmp/foo.xml', GetFlag('output'))
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// A helper program for testing that Google Test parses the environment
-// variables correctly.
-
-#include <iostream>
-
-#include "gtest/gtest.h"
-#include "src/gtest-internal-inl.h"
-
-using ::std::cout;
-
-namespace testing {
-
-// The purpose of this is to make the test more realistic by ensuring
-// that the UnitTest singleton is created before main() is entered.
-// We don't actual run the TEST itself.
-TEST(GTestEnvVarTest, Dummy) {
-}
-
-void PrintFlag(const char* flag) {
- if (strcmp(flag, "break_on_failure") == 0) {
- cout << GTEST_FLAG(break_on_failure);
- return;
- }
-
- if (strcmp(flag, "catch_exceptions") == 0) {
- cout << GTEST_FLAG(catch_exceptions);
- return;
- }
-
- if (strcmp(flag, "color") == 0) {
- cout << GTEST_FLAG(color);
- return;
- }
-
- if (strcmp(flag, "death_test_style") == 0) {
- cout << GTEST_FLAG(death_test_style);
- return;
- }
-
- if (strcmp(flag, "death_test_use_fork") == 0) {
- cout << GTEST_FLAG(death_test_use_fork);
- return;
- }
-
- if (strcmp(flag, "filter") == 0) {
- cout << GTEST_FLAG(filter);
- return;
- }
-
- if (strcmp(flag, "output") == 0) {
- cout << GTEST_FLAG(output);
- return;
- }
-
- if (strcmp(flag, "print_time") == 0) {
- cout << GTEST_FLAG(print_time);
- return;
- }
-
- if (strcmp(flag, "repeat") == 0) {
- cout << GTEST_FLAG(repeat);
- return;
- }
-
- if (strcmp(flag, "stack_trace_depth") == 0) {
- cout << GTEST_FLAG(stack_trace_depth);
- return;
- }
-
- if (strcmp(flag, "throw_on_failure") == 0) {
- cout << GTEST_FLAG(throw_on_failure);
- return;
- }
-
- cout << "Invalid flag name " << flag
- << ". Valid names are break_on_failure, color, filter, etc.\n";
- exit(1);
-}
-
-} // namespace testing
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
-
- if (argc != 2) {
- cout << "Usage: googletest-env-var-test_ NAME_OF_FLAG\n";
- return 1;
- }
-
- testing::PrintFlag(argv[1]);
- return 0;
-}
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Google Test filepath utilities
-//
-// This file tests classes and functions used internally by
-// Google Test. They are subject to change without notice.
-//
-// This file is #included from gtest-internal.h.
-// Do not #include this file anywhere else!
-
-#include "gtest/internal/gtest-filepath.h"
-#include "gtest/gtest.h"
-#include "src/gtest-internal-inl.h"
-
-#if GTEST_OS_WINDOWS_MOBILE
-# include <windows.h> // NOLINT
-#elif GTEST_OS_WINDOWS
-# include <direct.h> // NOLINT
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-namespace testing {
-namespace internal {
-namespace {
-
-#if GTEST_OS_WINDOWS_MOBILE
-
-// Windows CE doesn't have the remove C function.
-int remove(const char* path) {
- LPCWSTR wpath = String::AnsiToUtf16(path);
- int ret = DeleteFile(wpath) ? 0 : -1;
- delete [] wpath;
- return ret;
-}
-// Windows CE doesn't have the _rmdir C function.
-int _rmdir(const char* path) {
- FilePath filepath(path);
- LPCWSTR wpath = String::AnsiToUtf16(
- filepath.RemoveTrailingPathSeparator().c_str());
- int ret = RemoveDirectory(wpath) ? 0 : -1;
- delete [] wpath;
- return ret;
-}
-
-#else
-
-TEST(GetCurrentDirTest, ReturnsCurrentDir) {
- const FilePath original_dir = FilePath::GetCurrentDir();
- EXPECT_FALSE(original_dir.IsEmpty());
-
- posix::ChDir(GTEST_PATH_SEP_);
- const FilePath cwd = FilePath::GetCurrentDir();
- posix::ChDir(original_dir.c_str());
-
-# if GTEST_OS_WINDOWS || GTEST_OS_OS2
-
- // Skips the ":".
- const char* const cwd_without_drive = strchr(cwd.c_str(), ':');
- ASSERT_TRUE(cwd_without_drive != NULL);
- EXPECT_STREQ(GTEST_PATH_SEP_, cwd_without_drive + 1);
-
-# else
-
- EXPECT_EQ(GTEST_PATH_SEP_, cwd.string());
-
-# endif
-}
-
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-TEST(IsEmptyTest, ReturnsTrueForEmptyPath) {
- EXPECT_TRUE(FilePath("").IsEmpty());
-}
-
-TEST(IsEmptyTest, ReturnsFalseForNonEmptyPath) {
- EXPECT_FALSE(FilePath("a").IsEmpty());
- EXPECT_FALSE(FilePath(".").IsEmpty());
- EXPECT_FALSE(FilePath("a/b").IsEmpty());
- EXPECT_FALSE(FilePath("a\\b\\").IsEmpty());
-}
-
-// RemoveDirectoryName "" -> ""
-TEST(RemoveDirectoryNameTest, WhenEmptyName) {
- EXPECT_EQ("", FilePath("").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName "afile" -> "afile"
-TEST(RemoveDirectoryNameTest, ButNoDirectory) {
- EXPECT_EQ("afile",
- FilePath("afile").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName "/afile" -> "afile"
-TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileName) {
- EXPECT_EQ("afile",
- FilePath(GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName "adir/" -> ""
-TEST(RemoveDirectoryNameTest, WhereThereIsNoFileName) {
- EXPECT_EQ("",
- FilePath("adir" GTEST_PATH_SEP_).RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName "adir/afile" -> "afile"
-TEST(RemoveDirectoryNameTest, ShouldGiveFileName) {
- EXPECT_EQ("afile",
- FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName "adir/subdir/afile" -> "afile"
-TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileName) {
- EXPECT_EQ("afile",
- FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
- .RemoveDirectoryName().string());
-}
-
-#if GTEST_HAS_ALT_PATH_SEP_
-
-// Tests that RemoveDirectoryName() works with the alternate separator
-// on Windows.
-
-// RemoveDirectoryName("/afile") -> "afile"
-TEST(RemoveDirectoryNameTest, RootFileShouldGiveFileNameForAlternateSeparator) {
- EXPECT_EQ("afile", FilePath("/afile").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName("adir/") -> ""
-TEST(RemoveDirectoryNameTest, WhereThereIsNoFileNameForAlternateSeparator) {
- EXPECT_EQ("", FilePath("adir/").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName("adir/afile") -> "afile"
-TEST(RemoveDirectoryNameTest, ShouldGiveFileNameForAlternateSeparator) {
- EXPECT_EQ("afile", FilePath("adir/afile").RemoveDirectoryName().string());
-}
-
-// RemoveDirectoryName("adir/subdir/afile") -> "afile"
-TEST(RemoveDirectoryNameTest, ShouldAlsoGiveFileNameForAlternateSeparator) {
- EXPECT_EQ("afile",
- FilePath("adir/subdir/afile").RemoveDirectoryName().string());
-}
-
-#endif
-
-// RemoveFileName "" -> "./"
-TEST(RemoveFileNameTest, EmptyName) {
-#if GTEST_OS_WINDOWS_MOBILE
- // On Windows CE, we use the root as the current directory.
- EXPECT_EQ(GTEST_PATH_SEP_, FilePath("").RemoveFileName().string());
-#else
- EXPECT_EQ("." GTEST_PATH_SEP_, FilePath("").RemoveFileName().string());
-#endif
-}
-
-// RemoveFileName "adir/" -> "adir/"
-TEST(RemoveFileNameTest, ButNoFile) {
- EXPECT_EQ("adir" GTEST_PATH_SEP_,
- FilePath("adir" GTEST_PATH_SEP_).RemoveFileName().string());
-}
-
-// RemoveFileName "adir/afile" -> "adir/"
-TEST(RemoveFileNameTest, GivesDirName) {
- EXPECT_EQ("adir" GTEST_PATH_SEP_,
- FilePath("adir" GTEST_PATH_SEP_ "afile").RemoveFileName().string());
-}
-
-// RemoveFileName "adir/subdir/afile" -> "adir/subdir/"
-TEST(RemoveFileNameTest, GivesDirAndSubDirName) {
- EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
- FilePath("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_ "afile")
- .RemoveFileName().string());
-}
-
-// RemoveFileName "/afile" -> "/"
-TEST(RemoveFileNameTest, GivesRootDir) {
- EXPECT_EQ(GTEST_PATH_SEP_,
- FilePath(GTEST_PATH_SEP_ "afile").RemoveFileName().string());
-}
-
-#if GTEST_HAS_ALT_PATH_SEP_
-
-// Tests that RemoveFileName() works with the alternate separator on
-// Windows.
-
-// RemoveFileName("adir/") -> "adir/"
-TEST(RemoveFileNameTest, ButNoFileForAlternateSeparator) {
- EXPECT_EQ("adir" GTEST_PATH_SEP_,
- FilePath("adir/").RemoveFileName().string());
-}
-
-// RemoveFileName("adir/afile") -> "adir/"
-TEST(RemoveFileNameTest, GivesDirNameForAlternateSeparator) {
- EXPECT_EQ("adir" GTEST_PATH_SEP_,
- FilePath("adir/afile").RemoveFileName().string());
-}
-
-// RemoveFileName("adir/subdir/afile") -> "adir/subdir/"
-TEST(RemoveFileNameTest, GivesDirAndSubDirNameForAlternateSeparator) {
- EXPECT_EQ("adir" GTEST_PATH_SEP_ "subdir" GTEST_PATH_SEP_,
- FilePath("adir/subdir/afile").RemoveFileName().string());
-}
-
-// RemoveFileName("/afile") -> "\"
-TEST(RemoveFileNameTest, GivesRootDirForAlternateSeparator) {
- EXPECT_EQ(GTEST_PATH_SEP_, FilePath("/afile").RemoveFileName().string());
-}
-
-#endif
-
-TEST(MakeFileNameTest, GenerateWhenNumberIsZero) {
- FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
- 0, "xml");
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
-}
-
-TEST(MakeFileNameTest, GenerateFileNameNumberGtZero) {
- FilePath actual = FilePath::MakeFileName(FilePath("foo"), FilePath("bar"),
- 12, "xml");
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
-}
-
-TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberIsZero) {
- FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
- FilePath("bar"), 0, "xml");
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
-}
-
-TEST(MakeFileNameTest, GenerateFileNameWithSlashNumberGtZero) {
- FilePath actual = FilePath::MakeFileName(FilePath("foo" GTEST_PATH_SEP_),
- FilePath("bar"), 12, "xml");
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar_12.xml", actual.string());
-}
-
-TEST(MakeFileNameTest, GenerateWhenNumberIsZeroAndDirIsEmpty) {
- FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
- 0, "xml");
- EXPECT_EQ("bar.xml", actual.string());
-}
-
-TEST(MakeFileNameTest, GenerateWhenNumberIsNotZeroAndDirIsEmpty) {
- FilePath actual = FilePath::MakeFileName(FilePath(""), FilePath("bar"),
- 14, "xml");
- EXPECT_EQ("bar_14.xml", actual.string());
-}
-
-TEST(ConcatPathsTest, WorksWhenDirDoesNotEndWithPathSep) {
- FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
- FilePath("bar.xml"));
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
-}
-
-TEST(ConcatPathsTest, WorksWhenPath1EndsWithPathSep) {
- FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_),
- FilePath("bar.xml"));
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar.xml", actual.string());
-}
-
-TEST(ConcatPathsTest, Path1BeingEmpty) {
- FilePath actual = FilePath::ConcatPaths(FilePath(""),
- FilePath("bar.xml"));
- EXPECT_EQ("bar.xml", actual.string());
-}
-
-TEST(ConcatPathsTest, Path2BeingEmpty) {
- FilePath actual = FilePath::ConcatPaths(FilePath("foo"), FilePath(""));
- EXPECT_EQ("foo" GTEST_PATH_SEP_, actual.string());
-}
-
-TEST(ConcatPathsTest, BothPathBeingEmpty) {
- FilePath actual = FilePath::ConcatPaths(FilePath(""),
- FilePath(""));
- EXPECT_EQ("", actual.string());
-}
-
-TEST(ConcatPathsTest, Path1ContainsPathSep) {
- FilePath actual = FilePath::ConcatPaths(FilePath("foo" GTEST_PATH_SEP_ "bar"),
- FilePath("foobar.xml"));
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "foobar.xml",
- actual.string());
-}
-
-TEST(ConcatPathsTest, Path2ContainsPathSep) {
- FilePath actual = FilePath::ConcatPaths(
- FilePath("foo" GTEST_PATH_SEP_),
- FilePath("bar" GTEST_PATH_SEP_ "bar.xml"));
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_ "bar.xml",
- actual.string());
-}
-
-TEST(ConcatPathsTest, Path2EndsWithPathSep) {
- FilePath actual = FilePath::ConcatPaths(FilePath("foo"),
- FilePath("bar" GTEST_PATH_SEP_));
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_, actual.string());
-}
-
-// RemoveTrailingPathSeparator "" -> ""
-TEST(RemoveTrailingPathSeparatorTest, EmptyString) {
- EXPECT_EQ("", FilePath("").RemoveTrailingPathSeparator().string());
-}
-
-// RemoveTrailingPathSeparator "foo" -> "foo"
-TEST(RemoveTrailingPathSeparatorTest, FileNoSlashString) {
- EXPECT_EQ("foo", FilePath("foo").RemoveTrailingPathSeparator().string());
-}
-
-// RemoveTrailingPathSeparator "foo/" -> "foo"
-TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveTrailingSeparator) {
- EXPECT_EQ("foo",
- FilePath("foo" GTEST_PATH_SEP_).RemoveTrailingPathSeparator().string());
-#if GTEST_HAS_ALT_PATH_SEP_
- EXPECT_EQ("foo", FilePath("foo/").RemoveTrailingPathSeparator().string());
-#endif
-}
-
-// RemoveTrailingPathSeparator "foo/bar/" -> "foo/bar/"
-TEST(RemoveTrailingPathSeparatorTest, ShouldRemoveLastSeparator) {
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
- FilePath("foo" GTEST_PATH_SEP_ "bar" GTEST_PATH_SEP_)
- .RemoveTrailingPathSeparator().string());
-}
-
-// RemoveTrailingPathSeparator "foo/bar" -> "foo/bar"
-TEST(RemoveTrailingPathSeparatorTest, ShouldReturnUnmodified) {
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
- FilePath("foo" GTEST_PATH_SEP_ "bar")
- .RemoveTrailingPathSeparator().string());
-}
-
-TEST(DirectoryTest, RootDirectoryExists) {
-#if GTEST_OS_WINDOWS // We are on Windows.
- char current_drive[_MAX_PATH]; // NOLINT
- current_drive[0] = static_cast<char>(_getdrive() + 'A' - 1);
- current_drive[1] = ':';
- current_drive[2] = '\\';
- current_drive[3] = '\0';
- EXPECT_TRUE(FilePath(current_drive).DirectoryExists());
-#else
- EXPECT_TRUE(FilePath("/").DirectoryExists());
-#endif // GTEST_OS_WINDOWS
-}
-
-#if GTEST_OS_WINDOWS
-TEST(DirectoryTest, RootOfWrongDriveDoesNotExists) {
- const int saved_drive_ = _getdrive();
- // Find a drive that doesn't exist. Start with 'Z' to avoid common ones.
- for (char drive = 'Z'; drive >= 'A'; drive--)
- if (_chdrive(drive - 'A' + 1) == -1) {
- char non_drive[_MAX_PATH]; // NOLINT
- non_drive[0] = drive;
- non_drive[1] = ':';
- non_drive[2] = '\\';
- non_drive[3] = '\0';
- EXPECT_FALSE(FilePath(non_drive).DirectoryExists());
- break;
- }
- _chdrive(saved_drive_);
-}
-#endif // GTEST_OS_WINDOWS
-
-#if !GTEST_OS_WINDOWS_MOBILE
-// Windows CE _does_ consider an empty directory to exist.
-TEST(DirectoryTest, EmptyPathDirectoryDoesNotExist) {
- EXPECT_FALSE(FilePath("").DirectoryExists());
-}
-#endif // !GTEST_OS_WINDOWS_MOBILE
-
-TEST(DirectoryTest, CurrentDirectoryExists) {
-#if GTEST_OS_WINDOWS // We are on Windows.
-# ifndef _WIN32_CE // Windows CE doesn't have a current directory.
-
- EXPECT_TRUE(FilePath(".").DirectoryExists());
- EXPECT_TRUE(FilePath(".\\").DirectoryExists());
-
-# endif // _WIN32_CE
-#else
- EXPECT_TRUE(FilePath(".").DirectoryExists());
- EXPECT_TRUE(FilePath("./").DirectoryExists());
-#endif // GTEST_OS_WINDOWS
-}
-
-// "foo/bar" == foo//bar" == "foo///bar"
-TEST(NormalizeTest, MultipleConsecutiveSepaparatorsInMidstring) {
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
- FilePath("foo" GTEST_PATH_SEP_ "bar").string());
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
- FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
- EXPECT_EQ("foo" GTEST_PATH_SEP_ "bar",
- FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_
- GTEST_PATH_SEP_ "bar").string());
-}
-
-// "/bar" == //bar" == "///bar"
-TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringStart) {
- EXPECT_EQ(GTEST_PATH_SEP_ "bar",
- FilePath(GTEST_PATH_SEP_ "bar").string());
- EXPECT_EQ(GTEST_PATH_SEP_ "bar",
- FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
- EXPECT_EQ(GTEST_PATH_SEP_ "bar",
- FilePath(GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_ "bar").string());
-}
-
-// "foo/" == foo//" == "foo///"
-TEST(NormalizeTest, MultipleConsecutiveSepaparatorsAtStringEnd) {
- EXPECT_EQ("foo" GTEST_PATH_SEP_,
- FilePath("foo" GTEST_PATH_SEP_).string());
- EXPECT_EQ("foo" GTEST_PATH_SEP_,
- FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
- EXPECT_EQ("foo" GTEST_PATH_SEP_,
- FilePath("foo" GTEST_PATH_SEP_ GTEST_PATH_SEP_ GTEST_PATH_SEP_).string());
-}
-
-#if GTEST_HAS_ALT_PATH_SEP_
-
-// Tests that separators at the end of the string are normalized
-// regardless of their combination (e.g. "foo\" =="foo/\" ==
-// "foo\\/").
-TEST(NormalizeTest, MixAlternateSeparatorAtStringEnd) {
- EXPECT_EQ("foo" GTEST_PATH_SEP_,
- FilePath("foo/").string());
- EXPECT_EQ("foo" GTEST_PATH_SEP_,
- FilePath("foo" GTEST_PATH_SEP_ "/").string());
- EXPECT_EQ("foo" GTEST_PATH_SEP_,
- FilePath("foo//" GTEST_PATH_SEP_).string());
-}
-
-#endif
-
-TEST(AssignmentOperatorTest, DefaultAssignedToNonDefault) {
- FilePath default_path;
- FilePath non_default_path("path");
- non_default_path = default_path;
- EXPECT_EQ("", non_default_path.string());
- EXPECT_EQ("", default_path.string()); // RHS var is unchanged.
-}
-
-TEST(AssignmentOperatorTest, NonDefaultAssignedToDefault) {
- FilePath non_default_path("path");
- FilePath default_path;
- default_path = non_default_path;
- EXPECT_EQ("path", default_path.string());
- EXPECT_EQ("path", non_default_path.string()); // RHS var is unchanged.
-}
-
-TEST(AssignmentOperatorTest, ConstAssignedToNonConst) {
- const FilePath const_default_path("const_path");
- FilePath non_default_path("path");
- non_default_path = const_default_path;
- EXPECT_EQ("const_path", non_default_path.string());
-}
-
-class DirectoryCreationTest : public Test {
- protected:
- void SetUp() override {
- testdata_path_.Set(FilePath(
- TempDir() + GetCurrentExecutableName().string() +
- "_directory_creation" GTEST_PATH_SEP_ "test" GTEST_PATH_SEP_));
- testdata_file_.Set(testdata_path_.RemoveTrailingPathSeparator());
-
- unique_file0_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
- 0, "txt"));
- unique_file1_.Set(FilePath::MakeFileName(testdata_path_, FilePath("unique"),
- 1, "txt"));
-
- remove(testdata_file_.c_str());
- remove(unique_file0_.c_str());
- remove(unique_file1_.c_str());
- posix::RmDir(testdata_path_.c_str());
- }
-
- void TearDown() override {
- remove(testdata_file_.c_str());
- remove(unique_file0_.c_str());
- remove(unique_file1_.c_str());
- posix::RmDir(testdata_path_.c_str());
- }
-
- void CreateTextFile(const char* filename) {
- FILE* f = posix::FOpen(filename, "w");
- fprintf(f, "text\n");
- fclose(f);
- }
-
- // Strings representing a directory and a file, with identical paths
- // except for the trailing separator character that distinquishes
- // a directory named 'test' from a file named 'test'. Example names:
- FilePath testdata_path_; // "/tmp/directory_creation/test/"
- FilePath testdata_file_; // "/tmp/directory_creation/test"
- FilePath unique_file0_; // "/tmp/directory_creation/test/unique.txt"
- FilePath unique_file1_; // "/tmp/directory_creation/test/unique_1.txt"
-};
-
-TEST_F(DirectoryCreationTest, CreateDirectoriesRecursively) {
- EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.string();
- EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
- EXPECT_TRUE(testdata_path_.DirectoryExists());
-}
-
-TEST_F(DirectoryCreationTest, CreateDirectoriesForAlreadyExistingPath) {
- EXPECT_FALSE(testdata_path_.DirectoryExists()) << testdata_path_.string();
- EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
- // Call 'create' again... should still succeed.
- EXPECT_TRUE(testdata_path_.CreateDirectoriesRecursively());
-}
-
-TEST_F(DirectoryCreationTest, CreateDirectoriesAndUniqueFilename) {
- FilePath file_path(FilePath::GenerateUniqueFileName(testdata_path_,
- FilePath("unique"), "txt"));
- EXPECT_EQ(unique_file0_.string(), file_path.string());
- EXPECT_FALSE(file_path.FileOrDirectoryExists()); // file not there
-
- testdata_path_.CreateDirectoriesRecursively();
- EXPECT_FALSE(file_path.FileOrDirectoryExists()); // file still not there
- CreateTextFile(file_path.c_str());
- EXPECT_TRUE(file_path.FileOrDirectoryExists());
-
- FilePath file_path2(FilePath::GenerateUniqueFileName(testdata_path_,
- FilePath("unique"), "txt"));
- EXPECT_EQ(unique_file1_.string(), file_path2.string());
- EXPECT_FALSE(file_path2.FileOrDirectoryExists()); // file not there
- CreateTextFile(file_path2.c_str());
- EXPECT_TRUE(file_path2.FileOrDirectoryExists());
-}
-
-TEST_F(DirectoryCreationTest, CreateDirectoriesFail) {
- // force a failure by putting a file where we will try to create a directory.
- CreateTextFile(testdata_file_.c_str());
- EXPECT_TRUE(testdata_file_.FileOrDirectoryExists());
- EXPECT_FALSE(testdata_file_.DirectoryExists());
- EXPECT_FALSE(testdata_file_.CreateDirectoriesRecursively());
-}
-
-TEST(NoDirectoryCreationTest, CreateNoDirectoriesForDefaultXmlFile) {
- const FilePath test_detail_xml("test_detail.xml");
- EXPECT_FALSE(test_detail_xml.CreateDirectoriesRecursively());
-}
-
-TEST(FilePathTest, DefaultConstructor) {
- FilePath fp;
- EXPECT_EQ("", fp.string());
-}
-
-TEST(FilePathTest, CharAndCopyConstructors) {
- const FilePath fp("spicy");
- EXPECT_EQ("spicy", fp.string());
-
- const FilePath fp_copy(fp);
- EXPECT_EQ("spicy", fp_copy.string());
-}
-
-TEST(FilePathTest, StringConstructor) {
- const FilePath fp(std::string("cider"));
- EXPECT_EQ("cider", fp.string());
-}
-
-TEST(FilePathTest, Set) {
- const FilePath apple("apple");
- FilePath mac("mac");
- mac.Set(apple); // Implement Set() since overloading operator= is forbidden.
- EXPECT_EQ("apple", mac.string());
- EXPECT_EQ("apple", apple.string());
-}
-
-TEST(FilePathTest, ToString) {
- const FilePath file("drink");
- EXPECT_EQ("drink", file.string());
-}
-
-TEST(FilePathTest, RemoveExtension) {
- EXPECT_EQ("app", FilePath("app.cc").RemoveExtension("cc").string());
- EXPECT_EQ("app", FilePath("app.exe").RemoveExtension("exe").string());
- EXPECT_EQ("APP", FilePath("APP.EXE").RemoveExtension("exe").string());
-}
-
-TEST(FilePathTest, RemoveExtensionWhenThereIsNoExtension) {
- EXPECT_EQ("app", FilePath("app").RemoveExtension("exe").string());
-}
-
-TEST(FilePathTest, IsDirectory) {
- EXPECT_FALSE(FilePath("cola").IsDirectory());
- EXPECT_TRUE(FilePath("koala" GTEST_PATH_SEP_).IsDirectory());
-#if GTEST_HAS_ALT_PATH_SEP_
- EXPECT_TRUE(FilePath("koala/").IsDirectory());
-#endif
-}
-
-TEST(FilePathTest, IsAbsolutePath) {
- EXPECT_FALSE(FilePath("is" GTEST_PATH_SEP_ "relative").IsAbsolutePath());
- EXPECT_FALSE(FilePath("").IsAbsolutePath());
-#if GTEST_OS_WINDOWS
- EXPECT_TRUE(FilePath("c:\\" GTEST_PATH_SEP_ "is_not"
- GTEST_PATH_SEP_ "relative").IsAbsolutePath());
- EXPECT_FALSE(FilePath("c:foo" GTEST_PATH_SEP_ "bar").IsAbsolutePath());
- EXPECT_TRUE(FilePath("c:/" GTEST_PATH_SEP_ "is_not"
- GTEST_PATH_SEP_ "relative").IsAbsolutePath());
-#else
- EXPECT_TRUE(FilePath(GTEST_PATH_SEP_ "is_not" GTEST_PATH_SEP_ "relative")
- .IsAbsolutePath());
-#endif // GTEST_OS_WINDOWS
-}
-
-TEST(FilePathTest, IsRootDirectory) {
-#if GTEST_OS_WINDOWS
- EXPECT_TRUE(FilePath("a:\\").IsRootDirectory());
- EXPECT_TRUE(FilePath("Z:/").IsRootDirectory());
- EXPECT_TRUE(FilePath("e://").IsRootDirectory());
- EXPECT_FALSE(FilePath("").IsRootDirectory());
- EXPECT_FALSE(FilePath("b:").IsRootDirectory());
- EXPECT_FALSE(FilePath("b:a").IsRootDirectory());
- EXPECT_FALSE(FilePath("8:/").IsRootDirectory());
- EXPECT_FALSE(FilePath("c|/").IsRootDirectory());
-#else
- EXPECT_TRUE(FilePath("/").IsRootDirectory());
- EXPECT_TRUE(FilePath("//").IsRootDirectory());
- EXPECT_FALSE(FilePath("").IsRootDirectory());
- EXPECT_FALSE(FilePath("\\").IsRootDirectory());
- EXPECT_FALSE(FilePath("/x").IsRootDirectory());
-#endif
-}
-
-} // namespace
-} // namespace internal
-} // namespace testing
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2005 Google Inc. All Rights Reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for Google Test test filters.
-
-A user can specify which test(s) in a Google Test program to run via either
-the GTEST_FILTER environment variable or the --gtest_filter flag.
-This script tests such functionality by invoking
-googletest-filter-unittest_ (a program written with Google Test) with different
-environments and command line flags.
-
-Note that test sharding may also influence which tests are filtered. Therefore,
-we test that here also.
-"""
-
-import os
-import re
-try:
- from sets import Set as set # For Python 2.3 compatibility
-except ImportError:
- pass
-import sys
-import gtest_test_utils
-
-# Constants.
-
-# Checks if this platform can pass empty environment variables to child
-# processes. We set an env variable to an empty string and invoke a python
-# script in a subprocess to print whether the variable is STILL in
-# os.environ. We then use 'eval' to parse the child's output so that an
-# exception is thrown if the input is anything other than 'True' nor 'False'.
-CAN_PASS_EMPTY_ENV = False
-if sys.executable:
- os.environ['EMPTY_VAR'] = ''
- child = gtest_test_utils.Subprocess(
- [sys.executable, '-c', 'import os; print(\'EMPTY_VAR\' in os.environ)'])
- CAN_PASS_EMPTY_ENV = eval(child.output)
-
-
-# Check if this platform can unset environment variables in child processes.
-# We set an env variable to a non-empty string, unset it, and invoke
-# a python script in a subprocess to print whether the variable
-# is NO LONGER in os.environ.
-# We use 'eval' to parse the child's output so that an exception
-# is thrown if the input is neither 'True' nor 'False'.
-CAN_UNSET_ENV = False
-if sys.executable:
- os.environ['UNSET_VAR'] = 'X'
- del os.environ['UNSET_VAR']
- child = gtest_test_utils.Subprocess(
- [sys.executable, '-c', 'import os; print(\'UNSET_VAR\' not in os.environ)'
- ])
- CAN_UNSET_ENV = eval(child.output)
-
-
-# Checks if we should test with an empty filter. This doesn't
-# make sense on platforms that cannot pass empty env variables (Win32)
-# and on platforms that cannot unset variables (since we cannot tell
-# the difference between "" and NULL -- Borland and Solaris < 5.10)
-CAN_TEST_EMPTY_FILTER = (CAN_PASS_EMPTY_ENV and CAN_UNSET_ENV)
-
-
-# The environment variable for specifying the test filters.
-FILTER_ENV_VAR = 'GTEST_FILTER'
-
-# The environment variables for test sharding.
-TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
-SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
-SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
-
-# The command line flag for specifying the test filters.
-FILTER_FLAG = 'gtest_filter'
-
-# The command line flag for including disabled tests.
-ALSO_RUN_DISABLED_TESTS_FLAG = 'gtest_also_run_disabled_tests'
-
-# Command to run the googletest-filter-unittest_ program.
-COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-filter-unittest_')
-
-# Regex for determining whether parameterized tests are enabled in the binary.
-PARAM_TEST_REGEX = re.compile(r'/ParamTest')
-
-# Regex for parsing test case names from Google Test's output.
-TEST_CASE_REGEX = re.compile(r'^\[\-+\] \d+ tests? from (\w+(/\w+)?)')
-
-# Regex for parsing test names from Google Test's output.
-TEST_REGEX = re.compile(r'^\[\s*RUN\s*\].*\.(\w+(/\w+)?)')
-
-# The command line flag to tell Google Test to output the list of tests it
-# will run.
-LIST_TESTS_FLAG = '--gtest_list_tests'
-
-# Indicates whether Google Test supports death tests.
-SUPPORTS_DEATH_TESTS = 'HasDeathTest' in gtest_test_utils.Subprocess(
- [COMMAND, LIST_TESTS_FLAG]).output
-
-# Full names of all tests in googletest-filter-unittests_.
-PARAM_TESTS = [
- 'SeqP/ParamTest.TestX/0',
- 'SeqP/ParamTest.TestX/1',
- 'SeqP/ParamTest.TestY/0',
- 'SeqP/ParamTest.TestY/1',
- 'SeqQ/ParamTest.TestX/0',
- 'SeqQ/ParamTest.TestX/1',
- 'SeqQ/ParamTest.TestY/0',
- 'SeqQ/ParamTest.TestY/1',
- ]
-
-DISABLED_TESTS = [
- 'BarTest.DISABLED_TestFour',
- 'BarTest.DISABLED_TestFive',
- 'BazTest.DISABLED_TestC',
- 'DISABLED_FoobarTest.Test1',
- 'DISABLED_FoobarTest.DISABLED_Test2',
- 'DISABLED_FoobarbazTest.TestA',
- ]
-
-if SUPPORTS_DEATH_TESTS:
- DEATH_TESTS = [
- 'HasDeathTest.Test1',
- 'HasDeathTest.Test2',
- ]
-else:
- DEATH_TESTS = []
-
-# All the non-disabled tests.
-ACTIVE_TESTS = [
- 'FooTest.Abc',
- 'FooTest.Xyz',
-
- 'BarTest.TestOne',
- 'BarTest.TestTwo',
- 'BarTest.TestThree',
-
- 'BazTest.TestOne',
- 'BazTest.TestA',
- 'BazTest.TestB',
- ] + DEATH_TESTS + PARAM_TESTS
-
-param_tests_present = None
-
-# Utilities.
-
-environ = os.environ.copy()
-
-
-def SetEnvVar(env_var, value):
- """Sets the env variable to 'value'; unsets it when 'value' is None."""
-
- if value is not None:
- environ[env_var] = value
- elif env_var in environ:
- del environ[env_var]
-
-
-def RunAndReturnOutput(args = None):
- """Runs the test program and returns its output."""
-
- return gtest_test_utils.Subprocess([COMMAND] + (args or []),
- env=environ).output
-
-
-def RunAndExtractTestList(args = None):
- """Runs the test program and returns its exit code and a list of tests run."""
-
- p = gtest_test_utils.Subprocess([COMMAND] + (args or []), env=environ)
- tests_run = []
- test_case = ''
- test = ''
- for line in p.output.split('\n'):
- match = TEST_CASE_REGEX.match(line)
- if match is not None:
- test_case = match.group(1)
- else:
- match = TEST_REGEX.match(line)
- if match is not None:
- test = match.group(1)
- tests_run.append(test_case + '.' + test)
- return (tests_run, p.exit_code)
-
-
-def InvokeWithModifiedEnv(extra_env, function, *args, **kwargs):
- """Runs the given function and arguments in a modified environment."""
- try:
- original_env = environ.copy()
- environ.update(extra_env)
- return function(*args, **kwargs)
- finally:
- environ.clear()
- environ.update(original_env)
-
-
-def RunWithSharding(total_shards, shard_index, command):
- """Runs a test program shard and returns exit code and a list of tests run."""
-
- extra_env = {SHARD_INDEX_ENV_VAR: str(shard_index),
- TOTAL_SHARDS_ENV_VAR: str(total_shards)}
- return InvokeWithModifiedEnv(extra_env, RunAndExtractTestList, command)
-
-# The unit test.
-
-
-class GTestFilterUnitTest(gtest_test_utils.TestCase):
- """Tests the env variable or the command line flag to filter tests."""
-
- # Utilities.
-
- def AssertSetEqual(self, lhs, rhs):
- """Asserts that two sets are equal."""
-
- for elem in lhs:
- self.assert_(elem in rhs, '%s in %s' % (elem, rhs))
-
- for elem in rhs:
- self.assert_(elem in lhs, '%s in %s' % (elem, lhs))
-
- def AssertPartitionIsValid(self, set_var, list_of_sets):
- """Asserts that list_of_sets is a valid partition of set_var."""
-
- full_partition = []
- for slice_var in list_of_sets:
- full_partition.extend(slice_var)
- self.assertEqual(len(set_var), len(full_partition))
- self.assertEqual(set(set_var), set(full_partition))
-
- def AdjustForParameterizedTests(self, tests_to_run):
- """Adjust tests_to_run in case value parameterized tests are disabled."""
-
- global param_tests_present
- if not param_tests_present:
- return list(set(tests_to_run) - set(PARAM_TESTS))
- else:
- return tests_to_run
-
- def RunAndVerify(self, gtest_filter, tests_to_run):
- """Checks that the binary runs correct set of tests for a given filter."""
-
- tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
-
- # First, tests using the environment variable.
-
- # Windows removes empty variables from the environment when passing it
- # to a new process. This means it is impossible to pass an empty filter
- # into a process using the environment variable. However, we can still
- # test the case when the variable is not supplied (i.e., gtest_filter is
- # None).
- # pylint: disable-msg=C6403
- if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
- SetEnvVar(FILTER_ENV_VAR, gtest_filter)
- tests_run = RunAndExtractTestList()[0]
- SetEnvVar(FILTER_ENV_VAR, None)
- self.AssertSetEqual(tests_run, tests_to_run)
- # pylint: enable-msg=C6403
-
- # Next, tests using the command line flag.
-
- if gtest_filter is None:
- args = []
- else:
- args = ['--%s=%s' % (FILTER_FLAG, gtest_filter)]
-
- tests_run = RunAndExtractTestList(args)[0]
- self.AssertSetEqual(tests_run, tests_to_run)
-
- def RunAndVerifyWithSharding(self, gtest_filter, total_shards, tests_to_run,
- args=None, check_exit_0=False):
- """Checks that binary runs correct tests for the given filter and shard.
-
- Runs all shards of googletest-filter-unittest_ with the given filter, and
- verifies that the right set of tests were run. The union of tests run
- on each shard should be identical to tests_to_run, without duplicates.
- If check_exit_0, .
-
- Args:
- gtest_filter: A filter to apply to the tests.
- total_shards: A total number of shards to split test run into.
- tests_to_run: A set of tests expected to run.
- args : Arguments to pass to the to the test binary.
- check_exit_0: When set to a true value, make sure that all shards
- return 0.
- """
-
- tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
-
- # Windows removes empty variables from the environment when passing it
- # to a new process. This means it is impossible to pass an empty filter
- # into a process using the environment variable. However, we can still
- # test the case when the variable is not supplied (i.e., gtest_filter is
- # None).
- # pylint: disable-msg=C6403
- if CAN_TEST_EMPTY_FILTER or gtest_filter != '':
- SetEnvVar(FILTER_ENV_VAR, gtest_filter)
- partition = []
- for i in range(0, total_shards):
- (tests_run, exit_code) = RunWithSharding(total_shards, i, args)
- if check_exit_0:
- self.assertEqual(0, exit_code)
- partition.append(tests_run)
-
- self.AssertPartitionIsValid(tests_to_run, partition)
- SetEnvVar(FILTER_ENV_VAR, None)
- # pylint: enable-msg=C6403
-
- def RunAndVerifyAllowingDisabled(self, gtest_filter, tests_to_run):
- """Checks that the binary runs correct set of tests for the given filter.
-
- Runs googletest-filter-unittest_ with the given filter, and enables
- disabled tests. Verifies that the right set of tests were run.
-
- Args:
- gtest_filter: A filter to apply to the tests.
- tests_to_run: A set of tests expected to run.
- """
-
- tests_to_run = self.AdjustForParameterizedTests(tests_to_run)
-
- # Construct the command line.
- args = ['--%s' % ALSO_RUN_DISABLED_TESTS_FLAG]
- if gtest_filter is not None:
- args.append('--%s=%s' % (FILTER_FLAG, gtest_filter))
-
- tests_run = RunAndExtractTestList(args)[0]
- self.AssertSetEqual(tests_run, tests_to_run)
-
- def setUp(self):
- """Sets up test case.
-
- Determines whether value-parameterized tests are enabled in the binary and
- sets the flags accordingly.
- """
-
- global param_tests_present
- if param_tests_present is None:
- param_tests_present = PARAM_TEST_REGEX.search(
- RunAndReturnOutput()) is not None
-
- def testDefaultBehavior(self):
- """Tests the behavior of not specifying the filter."""
-
- self.RunAndVerify(None, ACTIVE_TESTS)
-
- def testDefaultBehaviorWithShards(self):
- """Tests the behavior without the filter, with sharding enabled."""
-
- self.RunAndVerifyWithSharding(None, 1, ACTIVE_TESTS)
- self.RunAndVerifyWithSharding(None, 2, ACTIVE_TESTS)
- self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) - 1, ACTIVE_TESTS)
- self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS), ACTIVE_TESTS)
- self.RunAndVerifyWithSharding(None, len(ACTIVE_TESTS) + 1, ACTIVE_TESTS)
-
- def testEmptyFilter(self):
- """Tests an empty filter."""
-
- self.RunAndVerify('', [])
- self.RunAndVerifyWithSharding('', 1, [])
- self.RunAndVerifyWithSharding('', 2, [])
-
- def testBadFilter(self):
- """Tests a filter that matches nothing."""
-
- self.RunAndVerify('BadFilter', [])
- self.RunAndVerifyAllowingDisabled('BadFilter', [])
-
- def testFullName(self):
- """Tests filtering by full name."""
-
- self.RunAndVerify('FooTest.Xyz', ['FooTest.Xyz'])
- self.RunAndVerifyAllowingDisabled('FooTest.Xyz', ['FooTest.Xyz'])
- self.RunAndVerifyWithSharding('FooTest.Xyz', 5, ['FooTest.Xyz'])
-
- def testUniversalFilters(self):
- """Tests filters that match everything."""
-
- self.RunAndVerify('*', ACTIVE_TESTS)
- self.RunAndVerify('*.*', ACTIVE_TESTS)
- self.RunAndVerifyWithSharding('*.*', len(ACTIVE_TESTS) - 3, ACTIVE_TESTS)
- self.RunAndVerifyAllowingDisabled('*', ACTIVE_TESTS + DISABLED_TESTS)
- self.RunAndVerifyAllowingDisabled('*.*', ACTIVE_TESTS + DISABLED_TESTS)
-
- def testFilterByTestCase(self):
- """Tests filtering by test case name."""
-
- self.RunAndVerify('FooTest.*', ['FooTest.Abc', 'FooTest.Xyz'])
-
- BAZ_TESTS = ['BazTest.TestOne', 'BazTest.TestA', 'BazTest.TestB']
- self.RunAndVerify('BazTest.*', BAZ_TESTS)
- self.RunAndVerifyAllowingDisabled('BazTest.*',
- BAZ_TESTS + ['BazTest.DISABLED_TestC'])
-
- def testFilterByTest(self):
- """Tests filtering by test name."""
-
- self.RunAndVerify('*.TestOne', ['BarTest.TestOne', 'BazTest.TestOne'])
-
- def testFilterDisabledTests(self):
- """Select only the disabled tests to run."""
-
- self.RunAndVerify('DISABLED_FoobarTest.Test1', [])
- self.RunAndVerifyAllowingDisabled('DISABLED_FoobarTest.Test1',
- ['DISABLED_FoobarTest.Test1'])
-
- self.RunAndVerify('*DISABLED_*', [])
- self.RunAndVerifyAllowingDisabled('*DISABLED_*', DISABLED_TESTS)
-
- self.RunAndVerify('*.DISABLED_*', [])
- self.RunAndVerifyAllowingDisabled('*.DISABLED_*', [
- 'BarTest.DISABLED_TestFour',
- 'BarTest.DISABLED_TestFive',
- 'BazTest.DISABLED_TestC',
- 'DISABLED_FoobarTest.DISABLED_Test2',
- ])
-
- self.RunAndVerify('DISABLED_*', [])
- self.RunAndVerifyAllowingDisabled('DISABLED_*', [
- 'DISABLED_FoobarTest.Test1',
- 'DISABLED_FoobarTest.DISABLED_Test2',
- 'DISABLED_FoobarbazTest.TestA',
- ])
-
- def testWildcardInTestCaseName(self):
- """Tests using wildcard in the test case name."""
-
- self.RunAndVerify('*a*.*', [
- 'BarTest.TestOne',
- 'BarTest.TestTwo',
- 'BarTest.TestThree',
-
- 'BazTest.TestOne',
- 'BazTest.TestA',
- 'BazTest.TestB', ] + DEATH_TESTS + PARAM_TESTS)
-
- def testWildcardInTestName(self):
- """Tests using wildcard in the test name."""
-
- self.RunAndVerify('*.*A*', ['FooTest.Abc', 'BazTest.TestA'])
-
- def testFilterWithoutDot(self):
- """Tests a filter that has no '.' in it."""
-
- self.RunAndVerify('*z*', [
- 'FooTest.Xyz',
-
- 'BazTest.TestOne',
- 'BazTest.TestA',
- 'BazTest.TestB',
- ])
-
- def testTwoPatterns(self):
- """Tests filters that consist of two patterns."""
-
- self.RunAndVerify('Foo*.*:*A*', [
- 'FooTest.Abc',
- 'FooTest.Xyz',
-
- 'BazTest.TestA',
- ])
-
- # An empty pattern + a non-empty one
- self.RunAndVerify(':*A*', ['FooTest.Abc', 'BazTest.TestA'])
-
- def testThreePatterns(self):
- """Tests filters that consist of three patterns."""
-
- self.RunAndVerify('*oo*:*A*:*One', [
- 'FooTest.Abc',
- 'FooTest.Xyz',
-
- 'BarTest.TestOne',
-
- 'BazTest.TestOne',
- 'BazTest.TestA',
- ])
-
- # The 2nd pattern is empty.
- self.RunAndVerify('*oo*::*One', [
- 'FooTest.Abc',
- 'FooTest.Xyz',
-
- 'BarTest.TestOne',
-
- 'BazTest.TestOne',
- ])
-
- # The last 2 patterns are empty.
- self.RunAndVerify('*oo*::', [
- 'FooTest.Abc',
- 'FooTest.Xyz',
- ])
-
- def testNegativeFilters(self):
- self.RunAndVerify('*-BazTest.TestOne', [
- 'FooTest.Abc',
- 'FooTest.Xyz',
-
- 'BarTest.TestOne',
- 'BarTest.TestTwo',
- 'BarTest.TestThree',
-
- 'BazTest.TestA',
- 'BazTest.TestB',
- ] + DEATH_TESTS + PARAM_TESTS)
-
- self.RunAndVerify('*-FooTest.Abc:BazTest.*', [
- 'FooTest.Xyz',
-
- 'BarTest.TestOne',
- 'BarTest.TestTwo',
- 'BarTest.TestThree',
- ] + DEATH_TESTS + PARAM_TESTS)
-
- self.RunAndVerify('BarTest.*-BarTest.TestOne', [
- 'BarTest.TestTwo',
- 'BarTest.TestThree',
- ])
-
- # Tests without leading '*'.
- self.RunAndVerify('-FooTest.Abc:FooTest.Xyz:BazTest.*', [
- 'BarTest.TestOne',
- 'BarTest.TestTwo',
- 'BarTest.TestThree',
- ] + DEATH_TESTS + PARAM_TESTS)
-
- # Value parameterized tests.
- self.RunAndVerify('*/*', PARAM_TESTS)
-
- # Value parameterized tests filtering by the sequence name.
- self.RunAndVerify('SeqP/*', [
- 'SeqP/ParamTest.TestX/0',
- 'SeqP/ParamTest.TestX/1',
- 'SeqP/ParamTest.TestY/0',
- 'SeqP/ParamTest.TestY/1',
- ])
-
- # Value parameterized tests filtering by the test name.
- self.RunAndVerify('*/0', [
- 'SeqP/ParamTest.TestX/0',
- 'SeqP/ParamTest.TestY/0',
- 'SeqQ/ParamTest.TestX/0',
- 'SeqQ/ParamTest.TestY/0',
- ])
-
- def testFlagOverridesEnvVar(self):
- """Tests that the filter flag overrides the filtering env. variable."""
-
- SetEnvVar(FILTER_ENV_VAR, 'Foo*')
- args = ['--%s=%s' % (FILTER_FLAG, '*One')]
- tests_run = RunAndExtractTestList(args)[0]
- SetEnvVar(FILTER_ENV_VAR, None)
-
- self.AssertSetEqual(tests_run, ['BarTest.TestOne', 'BazTest.TestOne'])
-
- def testShardStatusFileIsCreated(self):
- """Tests that the shard file is created if specified in the environment."""
-
- shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
- 'shard_status_file')
- self.assert_(not os.path.exists(shard_status_file))
-
- extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
- try:
- InvokeWithModifiedEnv(extra_env, RunAndReturnOutput)
- finally:
- self.assert_(os.path.exists(shard_status_file))
- os.remove(shard_status_file)
-
- def testShardStatusFileIsCreatedWithListTests(self):
- """Tests that the shard file is created with the "list_tests" flag."""
-
- shard_status_file = os.path.join(gtest_test_utils.GetTempDir(),
- 'shard_status_file2')
- self.assert_(not os.path.exists(shard_status_file))
-
- extra_env = {SHARD_STATUS_FILE_ENV_VAR: shard_status_file}
- try:
- output = InvokeWithModifiedEnv(extra_env,
- RunAndReturnOutput,
- [LIST_TESTS_FLAG])
- finally:
- # This assertion ensures that Google Test enumerated the tests as
- # opposed to running them.
- self.assert_('[==========]' not in output,
- 'Unexpected output during test enumeration.\n'
- 'Please ensure that LIST_TESTS_FLAG is assigned the\n'
- 'correct flag value for listing Google Test tests.')
-
- self.assert_(os.path.exists(shard_status_file))
- os.remove(shard_status_file)
-
- if SUPPORTS_DEATH_TESTS:
- def testShardingWorksWithDeathTests(self):
- """Tests integration with death tests and sharding."""
-
- gtest_filter = 'HasDeathTest.*:SeqP/*'
- expected_tests = [
- 'HasDeathTest.Test1',
- 'HasDeathTest.Test2',
-
- 'SeqP/ParamTest.TestX/0',
- 'SeqP/ParamTest.TestX/1',
- 'SeqP/ParamTest.TestY/0',
- 'SeqP/ParamTest.TestY/1',
- ]
-
- for flag in ['--gtest_death_test_style=threadsafe',
- '--gtest_death_test_style=fast']:
- self.RunAndVerifyWithSharding(gtest_filter, 3, expected_tests,
- check_exit_0=True, args=[flag])
- self.RunAndVerifyWithSharding(gtest_filter, 5, expected_tests,
- check_exit_0=True, args=[flag])
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Unit test for Google Test test filters.
-//
-// A user can specify which test(s) in a Google Test program to run via
-// either the GTEST_FILTER environment variable or the --gtest_filter
-// flag. This is used for testing such functionality.
-//
-// The program will be invoked from a Python unit test. Don't run it
-// directly.
-
-#include "gtest/gtest.h"
-
-namespace {
-
-// Test case FooTest.
-
-class FooTest : public testing::Test {
-};
-
-TEST_F(FooTest, Abc) {
-}
-
-TEST_F(FooTest, Xyz) {
- FAIL() << "Expected failure.";
-}
-
-// Test case BarTest.
-
-TEST(BarTest, TestOne) {
-}
-
-TEST(BarTest, TestTwo) {
-}
-
-TEST(BarTest, TestThree) {
-}
-
-TEST(BarTest, DISABLED_TestFour) {
- FAIL() << "Expected failure.";
-}
-
-TEST(BarTest, DISABLED_TestFive) {
- FAIL() << "Expected failure.";
-}
-
-// Test case BazTest.
-
-TEST(BazTest, TestOne) {
- FAIL() << "Expected failure.";
-}
-
-TEST(BazTest, TestA) {
-}
-
-TEST(BazTest, TestB) {
-}
-
-TEST(BazTest, DISABLED_TestC) {
- FAIL() << "Expected failure.";
-}
-
-// Test case HasDeathTest
-
-TEST(HasDeathTest, Test1) {
- EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
-}
-
-// We need at least two death tests to make sure that the all death tests
-// aren't on the first shard.
-TEST(HasDeathTest, Test2) {
- EXPECT_DEATH_IF_SUPPORTED(exit(1), ".*");
-}
-
-// Test case FoobarTest
-
-TEST(DISABLED_FoobarTest, Test1) {
- FAIL() << "Expected failure.";
-}
-
-TEST(DISABLED_FoobarTest, DISABLED_Test2) {
- FAIL() << "Expected failure.";
-}
-
-// Test case FoobarbazTest
-
-TEST(DISABLED_FoobarbazTest, TestA) {
- FAIL() << "Expected failure.";
-}
-
-class ParamTest : public testing::TestWithParam<int> {
-};
-
-TEST_P(ParamTest, TestX) {
-}
-
-TEST_P(ParamTest, TestY) {
-}
-
-INSTANTIATE_TEST_SUITE_P(SeqP, ParamTest, testing::Values(1, 2));
-INSTANTIATE_TEST_SUITE_P(SeqQ, ParamTest, testing::Values(5, 6));
-
-} // namespace
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-#!/usr/bin/env python
-# Copyright 2018, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for the gtest_json_output module."""
-
-import json
-import os
-import gtest_json_test_utils
-import gtest_test_utils
-
-GTEST_OUTPUT_SUBDIR = 'json_outfiles'
-GTEST_OUTPUT_1_TEST = 'gtest_xml_outfile1_test_'
-GTEST_OUTPUT_2_TEST = 'gtest_xml_outfile2_test_'
-
-EXPECTED_1 = {
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'name':
- u'AllTests',
- u'testsuites': [{
- u'name':
- u'PropertyOne',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'TestSomeProperties',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'PropertyOne',
- u'SetUpProp': u'1',
- u'TestSomeProperty': u'1',
- u'TearDownProp': u'1',
- }],
- }],
-}
-
-EXPECTED_2 = {
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'name':
- u'AllTests',
- u'testsuites': [{
- u'name':
- u'PropertyTwo',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'TestSomeProperties',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'timestamp': u'*',
- u'time': u'*',
- u'classname': u'PropertyTwo',
- u'SetUpProp': u'2',
- u'TestSomeProperty': u'2',
- u'TearDownProp': u'2',
- }],
- }],
-}
-
-
-class GTestJsonOutFilesTest(gtest_test_utils.TestCase):
- """Unit test for Google Test's JSON output functionality."""
-
- def setUp(self):
- # We want the trailing '/' that the last "" provides in os.path.join, for
- # telling Google Test to create an output directory instead of a single file
- # for xml output.
- self.output_dir_ = os.path.join(gtest_test_utils.GetTempDir(),
- GTEST_OUTPUT_SUBDIR, '')
- self.DeleteFilesAndDir()
-
- def tearDown(self):
- self.DeleteFilesAndDir()
-
- def DeleteFilesAndDir(self):
- try:
- os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + '.json'))
- except os.error:
- pass
- try:
- os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + '.json'))
- except os.error:
- pass
- try:
- os.rmdir(self.output_dir_)
- except os.error:
- pass
-
- def testOutfile1(self):
- self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_1)
-
- def testOutfile2(self):
- self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_2)
-
- def _TestOutFile(self, test_name, expected):
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
- command = [gtest_prog_path, '--gtest_output=json:%s' % self.output_dir_]
- p = gtest_test_utils.Subprocess(command,
- working_dir=gtest_test_utils.GetTempDir())
- self.assert_(p.exited)
- self.assertEquals(0, p.exit_code)
-
- output_file_name1 = test_name + '.json'
- output_file1 = os.path.join(self.output_dir_, output_file_name1)
- output_file_name2 = 'lt-' + output_file_name1
- output_file2 = os.path.join(self.output_dir_, output_file_name2)
- self.assert_(os.path.isfile(output_file1) or os.path.isfile(output_file2),
- output_file1)
-
- if os.path.isfile(output_file1):
- with open(output_file1) as f:
- actual = json.load(f)
- else:
- with open(output_file2) as f:
- actual = json.load(f)
- self.assertEqual(expected, gtest_json_test_utils.normalize(actual))
-
-
-if __name__ == '__main__':
- os.environ['GTEST_STACK_TRACE_DEPTH'] = '0'
- gtest_test_utils.Main()
+++ /dev/null
-#!/usr/bin/env python
-# Copyright 2018, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for the gtest_json_output module."""
-
-import datetime
-import errno
-import json
-import os
-import re
-import sys
-
-import gtest_json_test_utils
-import gtest_test_utils
-
-GTEST_FILTER_FLAG = '--gtest_filter'
-GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
-GTEST_OUTPUT_FLAG = '--gtest_output'
-GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.json'
-GTEST_PROGRAM_NAME = 'gtest_xml_output_unittest_'
-
-# The flag indicating stacktraces are not supported
-NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support'
-
-SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv
-
-if SUPPORTS_STACK_TRACES:
- STACK_TRACE_TEMPLATE = '\nStack trace:\n*'
-else:
- STACK_TRACE_TEMPLATE = ''
-
-EXPECTED_NON_EMPTY = {
- u'tests':
- 24,
- u'failures':
- 4,
- u'disabled':
- 2,
- u'errors':
- 0,
- u'timestamp':
- u'*',
- u'time':
- u'*',
- u'ad_hoc_property':
- u'42',
- u'name':
- u'AllTests',
- u'testsuites': [{
- u'name':
- u'SuccessfulTest',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'Succeeds',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'SuccessfulTest'
- }]
- }, {
- u'name':
- u'FailedTest',
- u'tests':
- 1,
- u'failures':
- 1,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name':
- u'Fails',
- u'status':
- u'RUN',
- u'result':
- u'COMPLETED',
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'classname':
- u'FailedTest',
- u'failures': [{
- u'failure': u'gtest_xml_output_unittest_.cc:*\n'
- u'Expected equality of these values:\n'
- u' 1\n 2' + STACK_TRACE_TEMPLATE,
- u'type': u''
- }]
- }]
- }, {
- u'name':
- u'DisabledTest',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 1,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'DISABLED_test_not_run',
- u'status': u'NOTRUN',
- u'result': u'SUPPRESSED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'DisabledTest'
- }]
- }, {
- u'name':
- u'SkippedTest',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'Skipped',
- u'status': u'RUN',
- u'result': u'SKIPPED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'SkippedTest'
- }]
- }, {
- u'name':
- u'MixedResultTest',
- u'tests':
- 3,
- u'failures':
- 1,
- u'disabled':
- 1,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'Succeeds',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'MixedResultTest'
- }, {
- u'name':
- u'Fails',
- u'status':
- u'RUN',
- u'result':
- u'COMPLETED',
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'classname':
- u'MixedResultTest',
- u'failures': [{
- u'failure': u'gtest_xml_output_unittest_.cc:*\n'
- u'Expected equality of these values:\n'
- u' 1\n 2' + STACK_TRACE_TEMPLATE,
- u'type': u''
- }, {
- u'failure': u'gtest_xml_output_unittest_.cc:*\n'
- u'Expected equality of these values:\n'
- u' 2\n 3' + STACK_TRACE_TEMPLATE,
- u'type': u''
- }]
- }, {
- u'name': u'DISABLED_test',
- u'status': u'NOTRUN',
- u'result': u'SUPPRESSED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'MixedResultTest'
- }]
- }, {
- u'name':
- u'XmlQuotingTest',
- u'tests':
- 1,
- u'failures':
- 1,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name':
- u'OutputsCData',
- u'status':
- u'RUN',
- u'result':
- u'COMPLETED',
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'classname':
- u'XmlQuotingTest',
- u'failures': [{
- u'failure': u'gtest_xml_output_unittest_.cc:*\n'
- u'Failed\nXML output: <?xml encoding="utf-8">'
- u'<top><![CDATA[cdata text]]></top>' +
- STACK_TRACE_TEMPLATE,
- u'type': u''
- }]
- }]
- }, {
- u'name':
- u'InvalidCharactersTest',
- u'tests':
- 1,
- u'failures':
- 1,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name':
- u'InvalidCharactersInMessage',
- u'status':
- u'RUN',
- u'result':
- u'COMPLETED',
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'classname':
- u'InvalidCharactersTest',
- u'failures': [{
- u'failure': u'gtest_xml_output_unittest_.cc:*\n'
- u'Failed\nInvalid characters in brackets'
- u' [\x01\x02]' + STACK_TRACE_TEMPLATE,
- u'type': u''
- }]
- }]
- }, {
- u'name':
- u'PropertyRecordingTest',
- u'tests':
- 4,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'SetUpTestSuite':
- u'yes',
- u'TearDownTestSuite':
- u'aye',
- u'testsuite': [{
- u'name': u'OneProperty',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'PropertyRecordingTest',
- u'key_1': u'1'
- }, {
- u'name': u'IntValuedProperty',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'PropertyRecordingTest',
- u'key_int': u'1'
- }, {
- u'name': u'ThreeProperties',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'PropertyRecordingTest',
- u'key_1': u'1',
- u'key_2': u'2',
- u'key_3': u'3'
- }, {
- u'name': u'TwoValuesForOneKeyUsesLastValue',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'PropertyRecordingTest',
- u'key_1': u'2'
- }]
- }, {
- u'name':
- u'NoFixtureTest',
- u'tests':
- 3,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'RecordProperty',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'NoFixtureTest',
- u'key': u'1'
- }, {
- u'name': u'ExternalUtilityThatCallsRecordIntValuedProperty',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'NoFixtureTest',
- u'key_for_utility_int': u'1'
- }, {
- u'name': u'ExternalUtilityThatCallsRecordStringValuedProperty',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'NoFixtureTest',
- u'key_for_utility_string': u'1'
- }]
- }, {
- u'name':
- u'TypedTest/0',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'HasTypeParamAttribute',
- u'type_param': u'int',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'TypedTest/0'
- }]
- }, {
- u'name':
- u'TypedTest/1',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'HasTypeParamAttribute',
- u'type_param': u'long',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'TypedTest/1'
- }]
- }, {
- u'name':
- u'Single/TypeParameterizedTestSuite/0',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'HasTypeParamAttribute',
- u'type_param': u'int',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'Single/TypeParameterizedTestSuite/0'
- }]
- }, {
- u'name':
- u'Single/TypeParameterizedTestSuite/1',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'HasTypeParamAttribute',
- u'type_param': u'long',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'Single/TypeParameterizedTestSuite/1'
- }]
- }, {
- u'name':
- u'Single/ValueParamTest',
- u'tests':
- 4,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'HasValueParamAttribute/0',
- u'value_param': u'33',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'Single/ValueParamTest'
- }, {
- u'name': u'HasValueParamAttribute/1',
- u'value_param': u'42',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'Single/ValueParamTest'
- }, {
- u'name': u'AnotherTestThatHasValueParamAttribute/0',
- u'value_param': u'33',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'Single/ValueParamTest'
- }, {
- u'name': u'AnotherTestThatHasValueParamAttribute/1',
- u'value_param': u'42',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'Single/ValueParamTest'
- }]
- }]
-}
-
-EXPECTED_FILTERED = {
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'name':
- u'AllTests',
- u'ad_hoc_property':
- u'42',
- u'testsuites': [{
- u'name':
- u'SuccessfulTest',
- u'tests':
- 1,
- u'failures':
- 0,
- u'disabled':
- 0,
- u'errors':
- 0,
- u'time':
- u'*',
- u'timestamp':
- u'*',
- u'testsuite': [{
- u'name': u'Succeeds',
- u'status': u'RUN',
- u'result': u'COMPLETED',
- u'time': u'*',
- u'timestamp': u'*',
- u'classname': u'SuccessfulTest',
- }]
- }],
-}
-
-EXPECTED_EMPTY = {
- u'tests': 0,
- u'failures': 0,
- u'disabled': 0,
- u'errors': 0,
- u'time': u'*',
- u'timestamp': u'*',
- u'name': u'AllTests',
- u'testsuites': [],
-}
-
-GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
-
-SUPPORTS_TYPED_TESTS = 'TypedTest' in gtest_test_utils.Subprocess(
- [GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False).output
-
-
-class GTestJsonOutputUnitTest(gtest_test_utils.TestCase):
- """Unit test for Google Test's JSON output functionality.
- """
-
- # This test currently breaks on platforms that do not support typed and
- # type-parameterized tests, so we don't run it under them.
- if SUPPORTS_TYPED_TESTS:
-
- def testNonEmptyJsonOutput(self):
- """Verifies JSON output for a Google Test binary with non-empty output.
-
- Runs a test program that generates a non-empty JSON output, and
- tests that the JSON output is expected.
- """
- self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY, 1)
-
- def testEmptyJsonOutput(self):
- """Verifies JSON output for a Google Test binary without actual tests.
-
- Runs a test program that generates an empty JSON output, and
- tests that the JSON output is expected.
- """
-
- self._TestJsonOutput('gtest_no_test_unittest', EXPECTED_EMPTY, 0)
-
- def testTimestampValue(self):
- """Checks whether the timestamp attribute in the JSON output is valid.
-
- Runs a test program that generates an empty JSON output, and checks if
- the timestamp attribute in the testsuites tag is valid.
- """
- actual = self._GetJsonOutput('gtest_no_test_unittest', [], 0)
- date_time_str = actual['timestamp']
- # datetime.strptime() is only available in Python 2.5+ so we have to
- # parse the expected datetime manually.
- match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str)
- self.assertTrue(
- re.match,
- 'JSON datettime string %s has incorrect format' % date_time_str)
- date_time_from_json = datetime.datetime(
- year=int(match.group(1)), month=int(match.group(2)),
- day=int(match.group(3)), hour=int(match.group(4)),
- minute=int(match.group(5)), second=int(match.group(6)))
-
- time_delta = abs(datetime.datetime.now() - date_time_from_json)
- # timestamp value should be near the current local time
- self.assertTrue(time_delta < datetime.timedelta(seconds=600),
- 'time_delta is %s' % time_delta)
-
- def testDefaultOutputFile(self):
- """Verifies the default output file name.
-
- Confirms that Google Test produces an JSON output file with the expected
- default name if no name is explicitly specified.
- """
- output_file = os.path.join(gtest_test_utils.GetTempDir(),
- GTEST_DEFAULT_OUTPUT_FILE)
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
- 'gtest_no_test_unittest')
- try:
- os.remove(output_file)
- except OSError:
- e = sys.exc_info()[1]
- if e.errno != errno.ENOENT:
- raise
-
- p = gtest_test_utils.Subprocess(
- [gtest_prog_path, '%s=json' % GTEST_OUTPUT_FLAG],
- working_dir=gtest_test_utils.GetTempDir())
- self.assert_(p.exited)
- self.assertEquals(0, p.exit_code)
- self.assert_(os.path.isfile(output_file))
-
- def testSuppressedJsonOutput(self):
- """Verifies that no JSON output is generated.
-
- Tests that no JSON file is generated if the default JSON listener is
- shut down before RUN_ALL_TESTS is invoked.
- """
-
- json_path = os.path.join(gtest_test_utils.GetTempDir(),
- GTEST_PROGRAM_NAME + 'out.json')
- if os.path.isfile(json_path):
- os.remove(json_path)
-
- command = [GTEST_PROGRAM_PATH,
- '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path),
- '--shut_down_xml']
- p = gtest_test_utils.Subprocess(command)
- if p.terminated_by_signal:
- # p.signal is available only if p.terminated_by_signal is True.
- self.assertFalse(
- p.terminated_by_signal,
- '%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal))
- else:
- self.assert_(p.exited)
- self.assertEquals(1, p.exit_code,
- "'%s' exited with code %s, which doesn't match "
- 'the expected exit code %s.'
- % (command, p.exit_code, 1))
-
- self.assert_(not os.path.isfile(json_path))
-
- def testFilteredTestJsonOutput(self):
- """Verifies JSON output when a filter is applied.
-
- Runs a test program that executes only some tests and verifies that
- non-selected tests do not show up in the JSON output.
- """
-
- self._TestJsonOutput(GTEST_PROGRAM_NAME, EXPECTED_FILTERED, 0,
- extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG])
-
- def _GetJsonOutput(self, gtest_prog_name, extra_args, expected_exit_code):
- """Returns the JSON output generated by running the program gtest_prog_name.
-
- Furthermore, the program's exit code must be expected_exit_code.
-
- Args:
- gtest_prog_name: Google Test binary name.
- extra_args: extra arguments to binary invocation.
- expected_exit_code: program's exit code.
- """
- json_path = os.path.join(gtest_test_utils.GetTempDir(),
- gtest_prog_name + 'out.json')
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
-
- command = (
- [gtest_prog_path, '%s=json:%s' % (GTEST_OUTPUT_FLAG, json_path)] +
- extra_args
- )
- p = gtest_test_utils.Subprocess(command)
- if p.terminated_by_signal:
- self.assert_(False,
- '%s was killed by signal %d' % (gtest_prog_name, p.signal))
- else:
- self.assert_(p.exited)
- self.assertEquals(expected_exit_code, p.exit_code,
- "'%s' exited with code %s, which doesn't match "
- 'the expected exit code %s.'
- % (command, p.exit_code, expected_exit_code))
- with open(json_path) as f:
- actual = json.load(f)
- return actual
-
- def _TestJsonOutput(self, gtest_prog_name, expected,
- expected_exit_code, extra_args=None):
- """Checks the JSON output generated by the Google Test binary.
-
- Asserts that the JSON document generated by running the program
- gtest_prog_name matches expected_json, a string containing another
- JSON document. Furthermore, the program's exit code must be
- expected_exit_code.
-
- Args:
- gtest_prog_name: Google Test binary name.
- expected: expected output.
- expected_exit_code: program's exit code.
- extra_args: extra arguments to binary invocation.
- """
-
- actual = self._GetJsonOutput(gtest_prog_name, extra_args or [],
- expected_exit_code)
- self.assertEqual(expected, gtest_json_test_utils.normalize(actual))
-
-
-if __name__ == '__main__':
- if NO_STACKTRACE_SUPPORT_FLAG in sys.argv:
- # unittest.main() can't handle unknown flags
- sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
-
- os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
- gtest_test_utils.Main()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for Google Test's --gtest_list_tests flag.
-
-A user can ask Google Test to list all tests by specifying the
---gtest_list_tests flag. This script tests such functionality
-by invoking googletest-list-tests-unittest_ (a program written with
-Google Test) the command line flags.
-"""
-
-import re
-import gtest_test_utils
-
-# Constants.
-
-# The command line flag for enabling/disabling listing all tests.
-LIST_TESTS_FLAG = 'gtest_list_tests'
-
-# Path to the googletest-list-tests-unittest_ program.
-EXE_PATH = gtest_test_utils.GetTestExecutablePath('googletest-list-tests-unittest_')
-
-# The expected output when running googletest-list-tests-unittest_ with
-# --gtest_list_tests
-EXPECTED_OUTPUT_NO_FILTER_RE = re.compile(r"""FooDeathTest\.
- Test1
-Foo\.
- Bar1
- Bar2
- DISABLED_Bar3
-Abc\.
- Xyz
- Def
-FooBar\.
- Baz
-FooTest\.
- Test1
- DISABLED_Test2
- Test3
-TypedTest/0\. # TypeParam = (VeryLo{245}|class VeryLo{239})\.\.\.
- TestA
- TestB
-TypedTest/1\. # TypeParam = int\s*\*( __ptr64)?
- TestA
- TestB
-TypedTest/2\. # TypeParam = .*MyArray<bool,\s*42>
- TestA
- TestB
-My/TypeParamTest/0\. # TypeParam = (VeryLo{245}|class VeryLo{239})\.\.\.
- TestA
- TestB
-My/TypeParamTest/1\. # TypeParam = int\s*\*( __ptr64)?
- TestA
- TestB
-My/TypeParamTest/2\. # TypeParam = .*MyArray<bool,\s*42>
- TestA
- TestB
-MyInstantiation/ValueParamTest\.
- TestA/0 # GetParam\(\) = one line
- TestA/1 # GetParam\(\) = two\\nlines
- TestA/2 # GetParam\(\) = a very\\nlo{241}\.\.\.
- TestB/0 # GetParam\(\) = one line
- TestB/1 # GetParam\(\) = two\\nlines
- TestB/2 # GetParam\(\) = a very\\nlo{241}\.\.\.
-""")
-
-# The expected output when running googletest-list-tests-unittest_ with
-# --gtest_list_tests and --gtest_filter=Foo*.
-EXPECTED_OUTPUT_FILTER_FOO_RE = re.compile(r"""FooDeathTest\.
- Test1
-Foo\.
- Bar1
- Bar2
- DISABLED_Bar3
-FooBar\.
- Baz
-FooTest\.
- Test1
- DISABLED_Test2
- Test3
-""")
-
-# Utilities.
-
-
-def Run(args):
- """Runs googletest-list-tests-unittest_ and returns the list of tests printed."""
-
- return gtest_test_utils.Subprocess([EXE_PATH] + args,
- capture_stderr=False).output
-
-
-# The unit test.
-
-
-class GTestListTestsUnitTest(gtest_test_utils.TestCase):
- """Tests using the --gtest_list_tests flag to list all tests."""
-
- def RunAndVerify(self, flag_value, expected_output_re, other_flag):
- """Runs googletest-list-tests-unittest_ and verifies that it prints
- the correct tests.
-
- Args:
- flag_value: value of the --gtest_list_tests flag;
- None if the flag should not be present.
- expected_output_re: regular expression that matches the expected
- output after running command;
- other_flag: a different flag to be passed to command
- along with gtest_list_tests;
- None if the flag should not be present.
- """
-
- if flag_value is None:
- flag = ''
- flag_expression = 'not set'
- elif flag_value == '0':
- flag = '--%s=0' % LIST_TESTS_FLAG
- flag_expression = '0'
- else:
- flag = '--%s' % LIST_TESTS_FLAG
- flag_expression = '1'
-
- args = [flag]
-
- if other_flag is not None:
- args += [other_flag]
-
- output = Run(args)
-
- if expected_output_re:
- self.assert_(
- expected_output_re.match(output),
- ('when %s is %s, the output of "%s" is "%s",\n'
- 'which does not match regex "%s"' %
- (LIST_TESTS_FLAG, flag_expression, ' '.join(args), output,
- expected_output_re.pattern)))
- else:
- self.assert_(
- not EXPECTED_OUTPUT_NO_FILTER_RE.match(output),
- ('when %s is %s, the output of "%s" is "%s"'%
- (LIST_TESTS_FLAG, flag_expression, ' '.join(args), output)))
-
- def testDefaultBehavior(self):
- """Tests the behavior of the default mode."""
-
- self.RunAndVerify(flag_value=None,
- expected_output_re=None,
- other_flag=None)
-
- def testFlag(self):
- """Tests using the --gtest_list_tests flag."""
-
- self.RunAndVerify(flag_value='0',
- expected_output_re=None,
- other_flag=None)
- self.RunAndVerify(flag_value='1',
- expected_output_re=EXPECTED_OUTPUT_NO_FILTER_RE,
- other_flag=None)
-
- def testOverrideNonFilterFlags(self):
- """Tests that --gtest_list_tests overrides the non-filter flags."""
-
- self.RunAndVerify(flag_value='1',
- expected_output_re=EXPECTED_OUTPUT_NO_FILTER_RE,
- other_flag='--gtest_break_on_failure')
-
- def testWithFilterFlags(self):
- """Tests that --gtest_list_tests takes into account the
- --gtest_filter flag."""
-
- self.RunAndVerify(flag_value='1',
- expected_output_re=EXPECTED_OUTPUT_FILTER_FOO_RE,
- other_flag='--gtest_filter=Foo*')
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Unit test for Google Test's --gtest_list_tests flag.
-//
-// A user can ask Google Test to list all tests that will run
-// so that when using a filter, a user will know what
-// tests to look for. The tests will not be run after listing.
-//
-// This program will be invoked from a Python unit test.
-// Don't run it directly.
-
-#include "gtest/gtest.h"
-
-// Several different test cases and tests that will be listed.
-TEST(Foo, Bar1) {
-}
-
-TEST(Foo, Bar2) {
-}
-
-TEST(Foo, DISABLED_Bar3) {
-}
-
-TEST(Abc, Xyz) {
-}
-
-TEST(Abc, Def) {
-}
-
-TEST(FooBar, Baz) {
-}
-
-class FooTest : public testing::Test {
-};
-
-TEST_F(FooTest, Test1) {
-}
-
-TEST_F(FooTest, DISABLED_Test2) {
-}
-
-TEST_F(FooTest, Test3) {
-}
-
-TEST(FooDeathTest, Test1) {
-}
-
-// A group of value-parameterized tests.
-
-class MyType {
- public:
- explicit MyType(const std::string& a_value) : value_(a_value) {}
-
- const std::string& value() const { return value_; }
-
- private:
- std::string value_;
-};
-
-// Teaches Google Test how to print a MyType.
-void PrintTo(const MyType& x, std::ostream* os) {
- *os << x.value();
-}
-
-class ValueParamTest : public testing::TestWithParam<MyType> {
-};
-
-TEST_P(ValueParamTest, TestA) {
-}
-
-TEST_P(ValueParamTest, TestB) {
-}
-
-INSTANTIATE_TEST_SUITE_P(
- MyInstantiation, ValueParamTest,
- testing::Values(MyType("one line"),
- MyType("two\nlines"),
- MyType("a very\nloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line"))); // NOLINT
-
-// A group of typed tests.
-
-// A deliberately long type name for testing the line-truncating
-// behavior when printing a type parameter.
-class VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName { // NOLINT
-};
-
-template <typename T>
-class TypedTest : public testing::Test {
-};
-
-template <typename T, int kSize>
-class MyArray {
-};
-
-typedef testing::Types<VeryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooogName, // NOLINT
- int*, MyArray<bool, 42> > MyTypes;
-
-TYPED_TEST_SUITE(TypedTest, MyTypes);
-
-TYPED_TEST(TypedTest, TestA) {
-}
-
-TYPED_TEST(TypedTest, TestB) {
-}
-
-// A group of type-parameterized tests.
-
-template <typename T>
-class TypeParamTest : public testing::Test {
-};
-
-TYPED_TEST_SUITE_P(TypeParamTest);
-
-TYPED_TEST_P(TypeParamTest, TestA) {
-}
-
-TYPED_TEST_P(TypeParamTest, TestB) {
-}
-
-REGISTER_TYPED_TEST_SUITE_P(TypeParamTest, TestA, TestB);
-
-INSTANTIATE_TYPED_TEST_SUITE_P(My, TypeParamTest, MyTypes);
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2009 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This file verifies Google Test event listeners receive events at the
-// right times.
-
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "gtest/internal/custom/gtest.h"
-
-using ::testing::AddGlobalTestEnvironment;
-using ::testing::Environment;
-using ::testing::InitGoogleTest;
-using ::testing::Test;
-using ::testing::TestSuite;
-using ::testing::TestEventListener;
-using ::testing::TestInfo;
-using ::testing::TestPartResult;
-using ::testing::UnitTest;
-
-// Used by tests to register their events.
-std::vector<std::string>* g_events = nullptr;
-
-namespace testing {
-namespace internal {
-
-class EventRecordingListener : public TestEventListener {
- public:
- explicit EventRecordingListener(const char* name) : name_(name) {}
-
- protected:
- void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnTestProgramStart"));
- }
-
- void OnTestIterationStart(const UnitTest& /*unit_test*/,
- int iteration) override {
- Message message;
- message << GetFullMethodName("OnTestIterationStart")
- << "(" << iteration << ")";
- g_events->push_back(message.GetString());
- }
-
- void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
- }
-
- void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
- }
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseStart(const TestCase& /*test_case*/) override {
- g_events->push_back(GetFullMethodName("OnTestCaseStart"));
- }
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- void OnTestStart(const TestInfo& /*test_info*/) override {
- g_events->push_back(GetFullMethodName("OnTestStart"));
- }
-
- void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {
- g_events->push_back(GetFullMethodName("OnTestPartResult"));
- }
-
- void OnTestEnd(const TestInfo& /*test_info*/) override {
- g_events->push_back(GetFullMethodName("OnTestEnd"));
- }
-
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
- void OnTestCaseEnd(const TestCase& /*test_case*/) override {
- g_events->push_back(GetFullMethodName("OnTestCaseEnd"));
- }
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
- }
-
- void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
- }
-
- void OnTestIterationEnd(const UnitTest& /*unit_test*/,
- int iteration) override {
- Message message;
- message << GetFullMethodName("OnTestIterationEnd")
- << "(" << iteration << ")";
- g_events->push_back(message.GetString());
- }
-
- void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
- }
-
- private:
- std::string GetFullMethodName(const char* name) {
- return name_ + "." + name;
- }
-
- std::string name_;
-};
-
-// This listener is using OnTestSuiteStart, OnTestSuiteEnd API
-class EventRecordingListener2 : public TestEventListener {
- public:
- explicit EventRecordingListener2(const char* name) : name_(name) {}
-
- protected:
- void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnTestProgramStart"));
- }
-
- void OnTestIterationStart(const UnitTest& /*unit_test*/,
- int iteration) override {
- Message message;
- message << GetFullMethodName("OnTestIterationStart") << "(" << iteration
- << ")";
- g_events->push_back(message.GetString());
- }
-
- void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpStart"));
- }
-
- void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsSetUpEnd"));
- }
-
- void OnTestSuiteStart(const TestSuite& /*test_suite*/) override {
- g_events->push_back(GetFullMethodName("OnTestSuiteStart"));
- }
-
- void OnTestStart(const TestInfo& /*test_info*/) override {
- g_events->push_back(GetFullMethodName("OnTestStart"));
- }
-
- void OnTestPartResult(const TestPartResult& /*test_part_result*/) override {
- g_events->push_back(GetFullMethodName("OnTestPartResult"));
- }
-
- void OnTestEnd(const TestInfo& /*test_info*/) override {
- g_events->push_back(GetFullMethodName("OnTestEnd"));
- }
-
- void OnTestSuiteEnd(const TestSuite& /*test_suite*/) override {
- g_events->push_back(GetFullMethodName("OnTestSuiteEnd"));
- }
-
- void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownStart"));
- }
-
- void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnEnvironmentsTearDownEnd"));
- }
-
- void OnTestIterationEnd(const UnitTest& /*unit_test*/,
- int iteration) override {
- Message message;
- message << GetFullMethodName("OnTestIterationEnd") << "(" << iteration
- << ")";
- g_events->push_back(message.GetString());
- }
-
- void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {
- g_events->push_back(GetFullMethodName("OnTestProgramEnd"));
- }
-
- private:
- std::string GetFullMethodName(const char* name) { return name_ + "." + name; }
-
- std::string name_;
-};
-
-class EnvironmentInvocationCatcher : public Environment {
- protected:
- void SetUp() override { g_events->push_back("Environment::SetUp"); }
-
- void TearDown() override { g_events->push_back("Environment::TearDown"); }
-};
-
-class ListenerTest : public Test {
- protected:
- static void SetUpTestSuite() {
- g_events->push_back("ListenerTest::SetUpTestSuite");
- }
-
- static void TearDownTestSuite() {
- g_events->push_back("ListenerTest::TearDownTestSuite");
- }
-
- void SetUp() override { g_events->push_back("ListenerTest::SetUp"); }
-
- void TearDown() override { g_events->push_back("ListenerTest::TearDown"); }
-};
-
-TEST_F(ListenerTest, DoesFoo) {
- // Test execution order within a test case is not guaranteed so we are not
- // recording the test name.
- g_events->push_back("ListenerTest::* Test Body");
- SUCCEED(); // Triggers OnTestPartResult.
-}
-
-TEST_F(ListenerTest, DoesBar) {
- g_events->push_back("ListenerTest::* Test Body");
- SUCCEED(); // Triggers OnTestPartResult.
-}
-
-} // namespace internal
-
-} // namespace testing
-
-using ::testing::internal::EnvironmentInvocationCatcher;
-using ::testing::internal::EventRecordingListener;
-using ::testing::internal::EventRecordingListener2;
-
-void VerifyResults(const std::vector<std::string>& data,
- const char* const* expected_data,
- size_t expected_data_size) {
- const size_t actual_size = data.size();
- // If the following assertion fails, a new entry will be appended to
- // data. Hence we save data.size() first.
- EXPECT_EQ(expected_data_size, actual_size);
-
- // Compares the common prefix.
- const size_t shorter_size = expected_data_size <= actual_size ?
- expected_data_size : actual_size;
- size_t i = 0;
- for (; i < shorter_size; ++i) {
- ASSERT_STREQ(expected_data[i], data[i].c_str())
- << "at position " << i;
- }
-
- // Prints extra elements in the actual data.
- for (; i < actual_size; ++i) {
- printf(" Actual event #%lu: %s\n",
- static_cast<unsigned long>(i), data[i].c_str());
- }
-}
-
-int main(int argc, char **argv) {
- std::vector<std::string> events;
- g_events = &events;
- InitGoogleTest(&argc, argv);
-
- UnitTest::GetInstance()->listeners().Append(
- new EventRecordingListener("1st"));
- UnitTest::GetInstance()->listeners().Append(
- new EventRecordingListener("2nd"));
- UnitTest::GetInstance()->listeners().Append(
- new EventRecordingListener2("3rd"));
-
- AddGlobalTestEnvironment(new EnvironmentInvocationCatcher);
-
- GTEST_CHECK_(events.size() == 0)
- << "AddGlobalTestEnvironment should not generate any events itself.";
-
- ::testing::GTEST_FLAG(repeat) = 2;
- int ret_val = RUN_ALL_TESTS();
-
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- // The deprecated OnTestSuiteStart/OnTestCaseStart events are included
- const char* const expected_events[] = {"1st.OnTestProgramStart",
- "2nd.OnTestProgramStart",
- "3rd.OnTestProgramStart",
- "1st.OnTestIterationStart(0)",
- "2nd.OnTestIterationStart(0)",
- "3rd.OnTestIterationStart(0)",
- "1st.OnEnvironmentsSetUpStart",
- "2nd.OnEnvironmentsSetUpStart",
- "3rd.OnEnvironmentsSetUpStart",
- "Environment::SetUp",
- "3rd.OnEnvironmentsSetUpEnd",
- "2nd.OnEnvironmentsSetUpEnd",
- "1st.OnEnvironmentsSetUpEnd",
- "3rd.OnTestSuiteStart",
- "1st.OnTestCaseStart",
- "2nd.OnTestCaseStart",
- "ListenerTest::SetUpTestSuite",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "ListenerTest::TearDownTestSuite",
- "3rd.OnTestSuiteEnd",
- "2nd.OnTestCaseEnd",
- "1st.OnTestCaseEnd",
- "1st.OnEnvironmentsTearDownStart",
- "2nd.OnEnvironmentsTearDownStart",
- "3rd.OnEnvironmentsTearDownStart",
- "Environment::TearDown",
- "3rd.OnEnvironmentsTearDownEnd",
- "2nd.OnEnvironmentsTearDownEnd",
- "1st.OnEnvironmentsTearDownEnd",
- "3rd.OnTestIterationEnd(0)",
- "2nd.OnTestIterationEnd(0)",
- "1st.OnTestIterationEnd(0)",
- "1st.OnTestIterationStart(1)",
- "2nd.OnTestIterationStart(1)",
- "3rd.OnTestIterationStart(1)",
- "1st.OnEnvironmentsSetUpStart",
- "2nd.OnEnvironmentsSetUpStart",
- "3rd.OnEnvironmentsSetUpStart",
- "Environment::SetUp",
- "3rd.OnEnvironmentsSetUpEnd",
- "2nd.OnEnvironmentsSetUpEnd",
- "1st.OnEnvironmentsSetUpEnd",
- "3rd.OnTestSuiteStart",
- "1st.OnTestCaseStart",
- "2nd.OnTestCaseStart",
- "ListenerTest::SetUpTestSuite",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "ListenerTest::TearDownTestSuite",
- "3rd.OnTestSuiteEnd",
- "2nd.OnTestCaseEnd",
- "1st.OnTestCaseEnd",
- "1st.OnEnvironmentsTearDownStart",
- "2nd.OnEnvironmentsTearDownStart",
- "3rd.OnEnvironmentsTearDownStart",
- "Environment::TearDown",
- "3rd.OnEnvironmentsTearDownEnd",
- "2nd.OnEnvironmentsTearDownEnd",
- "1st.OnEnvironmentsTearDownEnd",
- "3rd.OnTestIterationEnd(1)",
- "2nd.OnTestIterationEnd(1)",
- "1st.OnTestIterationEnd(1)",
- "3rd.OnTestProgramEnd",
- "2nd.OnTestProgramEnd",
- "1st.OnTestProgramEnd"};
-#else
- const char* const expected_events[] = {"1st.OnTestProgramStart",
- "2nd.OnTestProgramStart",
- "3rd.OnTestProgramStart",
- "1st.OnTestIterationStart(0)",
- "2nd.OnTestIterationStart(0)",
- "3rd.OnTestIterationStart(0)",
- "1st.OnEnvironmentsSetUpStart",
- "2nd.OnEnvironmentsSetUpStart",
- "3rd.OnEnvironmentsSetUpStart",
- "Environment::SetUp",
- "3rd.OnEnvironmentsSetUpEnd",
- "2nd.OnEnvironmentsSetUpEnd",
- "1st.OnEnvironmentsSetUpEnd",
- "3rd.OnTestSuiteStart",
- "ListenerTest::SetUpTestSuite",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "ListenerTest::TearDownTestSuite",
- "3rd.OnTestSuiteEnd",
- "1st.OnEnvironmentsTearDownStart",
- "2nd.OnEnvironmentsTearDownStart",
- "3rd.OnEnvironmentsTearDownStart",
- "Environment::TearDown",
- "3rd.OnEnvironmentsTearDownEnd",
- "2nd.OnEnvironmentsTearDownEnd",
- "1st.OnEnvironmentsTearDownEnd",
- "3rd.OnTestIterationEnd(0)",
- "2nd.OnTestIterationEnd(0)",
- "1st.OnTestIterationEnd(0)",
- "1st.OnTestIterationStart(1)",
- "2nd.OnTestIterationStart(1)",
- "3rd.OnTestIterationStart(1)",
- "1st.OnEnvironmentsSetUpStart",
- "2nd.OnEnvironmentsSetUpStart",
- "3rd.OnEnvironmentsSetUpStart",
- "Environment::SetUp",
- "3rd.OnEnvironmentsSetUpEnd",
- "2nd.OnEnvironmentsSetUpEnd",
- "1st.OnEnvironmentsSetUpEnd",
- "3rd.OnTestSuiteStart",
- "ListenerTest::SetUpTestSuite",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "1st.OnTestStart",
- "2nd.OnTestStart",
- "3rd.OnTestStart",
- "ListenerTest::SetUp",
- "ListenerTest::* Test Body",
- "1st.OnTestPartResult",
- "2nd.OnTestPartResult",
- "3rd.OnTestPartResult",
- "ListenerTest::TearDown",
- "3rd.OnTestEnd",
- "2nd.OnTestEnd",
- "1st.OnTestEnd",
- "ListenerTest::TearDownTestSuite",
- "3rd.OnTestSuiteEnd",
- "1st.OnEnvironmentsTearDownStart",
- "2nd.OnEnvironmentsTearDownStart",
- "3rd.OnEnvironmentsTearDownStart",
- "Environment::TearDown",
- "3rd.OnEnvironmentsTearDownEnd",
- "2nd.OnEnvironmentsTearDownEnd",
- "1st.OnEnvironmentsTearDownEnd",
- "3rd.OnTestIterationEnd(1)",
- "2nd.OnTestIterationEnd(1)",
- "1st.OnTestIterationEnd(1)",
- "3rd.OnTestProgramEnd",
- "2nd.OnTestProgramEnd",
- "1st.OnTestProgramEnd"};
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
-
- VerifyResults(events,
- expected_events,
- sizeof(expected_events)/sizeof(expected_events[0]));
-
- // We need to check manually for ad hoc test failures that happen after
- // RUN_ALL_TESTS finishes.
- if (UnitTest::GetInstance()->Failed())
- ret_val = 1;
-
- return ret_val;
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for the Message class.
-
-#include "gtest/gtest-message.h"
-
-#include "gtest/gtest.h"
-
-namespace {
-
-using ::testing::Message;
-
-// Tests the testing::Message class
-
-// Tests the default constructor.
-TEST(MessageTest, DefaultConstructor) {
- const Message msg;
- EXPECT_EQ("", msg.GetString());
-}
-
-// Tests the copy constructor.
-TEST(MessageTest, CopyConstructor) {
- const Message msg1("Hello");
- const Message msg2(msg1);
- EXPECT_EQ("Hello", msg2.GetString());
-}
-
-// Tests constructing a Message from a C-string.
-TEST(MessageTest, ConstructsFromCString) {
- Message msg("Hello");
- EXPECT_EQ("Hello", msg.GetString());
-}
-
-// Tests streaming a float.
-TEST(MessageTest, StreamsFloat) {
- const std::string s = (Message() << 1.23456F << " " << 2.34567F).GetString();
- // Both numbers should be printed with enough precision.
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "1.234560", s.c_str());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, " 2.345669", s.c_str());
-}
-
-// Tests streaming a double.
-TEST(MessageTest, StreamsDouble) {
- const std::string s = (Message() << 1260570880.4555497 << " "
- << 1260572265.1954534).GetString();
- // Both numbers should be printed with enough precision.
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "1260570880.45", s.c_str());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, " 1260572265.19", s.c_str());
-}
-
-// Tests streaming a non-char pointer.
-TEST(MessageTest, StreamsPointer) {
- int n = 0;
- int* p = &n;
- EXPECT_NE("(null)", (Message() << p).GetString());
-}
-
-// Tests streaming a NULL non-char pointer.
-TEST(MessageTest, StreamsNullPointer) {
- int* p = nullptr;
- EXPECT_EQ("(null)", (Message() << p).GetString());
-}
-
-// Tests streaming a C string.
-TEST(MessageTest, StreamsCString) {
- EXPECT_EQ("Foo", (Message() << "Foo").GetString());
-}
-
-// Tests streaming a NULL C string.
-TEST(MessageTest, StreamsNullCString) {
- char* p = nullptr;
- EXPECT_EQ("(null)", (Message() << p).GetString());
-}
-
-// Tests streaming std::string.
-TEST(MessageTest, StreamsString) {
- const ::std::string str("Hello");
- EXPECT_EQ("Hello", (Message() << str).GetString());
-}
-
-// Tests that we can output strings containing embedded NULs.
-TEST(MessageTest, StreamsStringWithEmbeddedNUL) {
- const char char_array_with_nul[] =
- "Here's a NUL\0 and some more string";
- const ::std::string string_with_nul(char_array_with_nul,
- sizeof(char_array_with_nul) - 1);
- EXPECT_EQ("Here's a NUL\\0 and some more string",
- (Message() << string_with_nul).GetString());
-}
-
-// Tests streaming a NUL char.
-TEST(MessageTest, StreamsNULChar) {
- EXPECT_EQ("\\0", (Message() << '\0').GetString());
-}
-
-// Tests streaming int.
-TEST(MessageTest, StreamsInt) {
- EXPECT_EQ("123", (Message() << 123).GetString());
-}
-
-// Tests that basic IO manipulators (endl, ends, and flush) can be
-// streamed to Message.
-TEST(MessageTest, StreamsBasicIoManip) {
- EXPECT_EQ("Line 1.\nA NUL char \\0 in line 2.",
- (Message() << "Line 1." << std::endl
- << "A NUL char " << std::ends << std::flush
- << " in line 2.").GetString());
-}
-
-// Tests Message::GetString()
-TEST(MessageTest, GetString) {
- Message msg;
- msg << 1 << " lamb";
- EXPECT_EQ("1 lamb", msg.GetString());
-}
-
-// Tests streaming a Message object to an ostream.
-TEST(MessageTest, StreamsToOStream) {
- Message msg("Hello");
- ::std::stringstream ss;
- ss << msg;
- EXPECT_EQ("Hello", testing::internal::StringStreamToString(&ss));
-}
-
-// Tests that a Message object doesn't take up too much stack space.
-TEST(MessageTest, DoesNotTakeUpMuchStackSpace) {
- EXPECT_LE(sizeof(Message), 16U);
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Google Test UnitTestOptions tests
-//
-// This file tests classes and functions used internally by
-// Google Test. They are subject to change without notice.
-//
-// This file is #included from gtest.cc, to avoid changing build or
-// make-files on Windows and other platforms. Do not #include this file
-// anywhere else!
-
-#include "gtest/gtest.h"
-
-#if GTEST_OS_WINDOWS_MOBILE
-# include <windows.h>
-#elif GTEST_OS_WINDOWS
-# include <direct.h>
-#endif // GTEST_OS_WINDOWS_MOBILE
-
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-namespace internal {
-namespace {
-
-// Turns the given relative path into an absolute path.
-FilePath GetAbsolutePathOf(const FilePath& relative_path) {
- return FilePath::ConcatPaths(FilePath::GetCurrentDir(), relative_path);
-}
-
-// Testing UnitTestOptions::GetOutputFormat/GetOutputFile.
-
-TEST(XmlOutputTest, GetOutputFormatDefault) {
- GTEST_FLAG(output) = "";
- EXPECT_STREQ("", UnitTestOptions::GetOutputFormat().c_str());
-}
-
-TEST(XmlOutputTest, GetOutputFormat) {
- GTEST_FLAG(output) = "xml:filename";
- EXPECT_STREQ("xml", UnitTestOptions::GetOutputFormat().c_str());
-}
-
-TEST(XmlOutputTest, GetOutputFileDefault) {
- GTEST_FLAG(output) = "";
- EXPECT_EQ(GetAbsolutePathOf(FilePath("test_detail.xml")).string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-}
-
-TEST(XmlOutputTest, GetOutputFileSingleFile) {
- GTEST_FLAG(output) = "xml:filename.abc";
- EXPECT_EQ(GetAbsolutePathOf(FilePath("filename.abc")).string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-}
-
-TEST(XmlOutputTest, GetOutputFileFromDirectoryPath) {
- GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
- const std::string expected_output_file =
- GetAbsolutePathOf(
- FilePath(std::string("path") + GTEST_PATH_SEP_ +
- GetCurrentExecutableName().string() + ".xml")).string();
- const std::string& output_file =
- UnitTestOptions::GetAbsolutePathToOutputFile();
-#if GTEST_OS_WINDOWS
- EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
-#else
- EXPECT_EQ(expected_output_file, output_file.c_str());
-#endif
-}
-
-TEST(OutputFileHelpersTest, GetCurrentExecutableName) {
- const std::string exe_str = GetCurrentExecutableName().string();
-#if GTEST_OS_WINDOWS
- const bool success =
- _strcmpi("googletest-options-test", exe_str.c_str()) == 0 ||
- _strcmpi("gtest-options-ex_test", exe_str.c_str()) == 0 ||
- _strcmpi("gtest_all_test", exe_str.c_str()) == 0 ||
- _strcmpi("gtest_dll_test", exe_str.c_str()) == 0;
-#elif GTEST_OS_OS2
- const bool success =
- strcasecmp("googletest-options-test", exe_str.c_str()) == 0 ||
- strcasecmp("gtest-options-ex_test", exe_str.c_str()) == 0 ||
- strcasecmp("gtest_all_test", exe_str.c_str()) == 0 ||
- strcasecmp("gtest_dll_test", exe_str.c_str()) == 0;
-#elif GTEST_OS_FUCHSIA
- const bool success = exe_str == "app";
-#else
- const bool success =
- exe_str == "googletest-options-test" ||
- exe_str == "gtest_all_test" ||
- exe_str == "lt-gtest_all_test" ||
- exe_str == "gtest_dll_test";
-#endif // GTEST_OS_WINDOWS
- if (!success)
- FAIL() << "GetCurrentExecutableName() returns " << exe_str;
-}
-
-#if !GTEST_OS_FUCHSIA
-
-class XmlOutputChangeDirTest : public Test {
- protected:
- void SetUp() override {
- original_working_dir_ = FilePath::GetCurrentDir();
- posix::ChDir("..");
- // This will make the test fail if run from the root directory.
- EXPECT_NE(original_working_dir_.string(),
- FilePath::GetCurrentDir().string());
- }
-
- void TearDown() override {
- posix::ChDir(original_working_dir_.string().c_str());
- }
-
- FilePath original_working_dir_;
-};
-
-TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefault) {
- GTEST_FLAG(output) = "";
- EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
- FilePath("test_detail.xml")).string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-}
-
-TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithDefaultXML) {
- GTEST_FLAG(output) = "xml";
- EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
- FilePath("test_detail.xml")).string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-}
-
-TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativeFile) {
- GTEST_FLAG(output) = "xml:filename.abc";
- EXPECT_EQ(FilePath::ConcatPaths(original_working_dir_,
- FilePath("filename.abc")).string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-}
-
-TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithRelativePath) {
- GTEST_FLAG(output) = "xml:path" GTEST_PATH_SEP_;
- const std::string expected_output_file =
- FilePath::ConcatPaths(
- original_working_dir_,
- FilePath(std::string("path") + GTEST_PATH_SEP_ +
- GetCurrentExecutableName().string() + ".xml")).string();
- const std::string& output_file =
- UnitTestOptions::GetAbsolutePathToOutputFile();
-#if GTEST_OS_WINDOWS
- EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
-#else
- EXPECT_EQ(expected_output_file, output_file.c_str());
-#endif
-}
-
-TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsoluteFile) {
-#if GTEST_OS_WINDOWS
- GTEST_FLAG(output) = "xml:c:\\tmp\\filename.abc";
- EXPECT_EQ(FilePath("c:\\tmp\\filename.abc").string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-#else
- GTEST_FLAG(output) ="xml:/tmp/filename.abc";
- EXPECT_EQ(FilePath("/tmp/filename.abc").string(),
- UnitTestOptions::GetAbsolutePathToOutputFile());
-#endif
-}
-
-TEST_F(XmlOutputChangeDirTest, PreserveOriginalWorkingDirWithAbsolutePath) {
-#if GTEST_OS_WINDOWS
- const std::string path = "c:\\tmp\\";
-#else
- const std::string path = "/tmp/";
-#endif
-
- GTEST_FLAG(output) = "xml:" + path;
- const std::string expected_output_file =
- path + GetCurrentExecutableName().string() + ".xml";
- const std::string& output_file =
- UnitTestOptions::GetAbsolutePathToOutputFile();
-
-#if GTEST_OS_WINDOWS
- EXPECT_STRCASEEQ(expected_output_file.c_str(), output_file.c_str());
-#else
- EXPECT_EQ(expected_output_file, output_file.c_str());
-#endif
-}
-
-#endif // !GTEST_OS_FUCHSIA
-
-} // namespace
-} // namespace internal
-} // namespace testing
+++ /dev/null
-The non-test part of the code is expected to have 2 failures.
-
-googletest-output-test_.cc:#: Failure
-Value of: false
- Actual: false
-Expected: true
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 2
- 3
-Stack trace: (omitted)
-
-\e[0;32m[==========] \e[mRunning 85 tests from 40 test suites.
-\e[0;32m[----------] \e[mGlobal test environment set-up.
-FooEnvironment::SetUp() called.
-BarEnvironment::SetUp() called.
-\e[0;32m[----------] \e[m1 test from ADeathTest
-\e[0;32m[ RUN ] \e[mADeathTest.ShouldRunFirst
-\e[0;32m[ OK ] \e[mADeathTest.ShouldRunFirst
-\e[0;32m[----------] \e[m1 test from ATypedDeathTest/0, where TypeParam = int
-\e[0;32m[ RUN ] \e[mATypedDeathTest/0.ShouldRunFirst
-\e[0;32m[ OK ] \e[mATypedDeathTest/0.ShouldRunFirst
-\e[0;32m[----------] \e[m1 test from ATypedDeathTest/1, where TypeParam = double
-\e[0;32m[ RUN ] \e[mATypedDeathTest/1.ShouldRunFirst
-\e[0;32m[ OK ] \e[mATypedDeathTest/1.ShouldRunFirst
-\e[0;32m[----------] \e[m1 test from My/ATypeParamDeathTest/0, where TypeParam = int
-\e[0;32m[ RUN ] \e[mMy/ATypeParamDeathTest/0.ShouldRunFirst
-\e[0;32m[ OK ] \e[mMy/ATypeParamDeathTest/0.ShouldRunFirst
-\e[0;32m[----------] \e[m1 test from My/ATypeParamDeathTest/1, where TypeParam = double
-\e[0;32m[ RUN ] \e[mMy/ATypeParamDeathTest/1.ShouldRunFirst
-\e[0;32m[ OK ] \e[mMy/ATypeParamDeathTest/1.ShouldRunFirst
-\e[0;32m[----------] \e[m2 tests from PassingTest
-\e[0;32m[ RUN ] \e[mPassingTest.PassingTest1
-\e[0;32m[ OK ] \e[mPassingTest.PassingTest1
-\e[0;32m[ RUN ] \e[mPassingTest.PassingTest2
-\e[0;32m[ OK ] \e[mPassingTest.PassingTest2
-\e[0;32m[----------] \e[m2 tests from NonfatalFailureTest
-\e[0;32m[ RUN ] \e[mNonfatalFailureTest.EscapesStringOperands
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- kGoldenString
- Which is: "\"Line"
- actual
- Which is: "actual \"string\""
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- golden
- Which is: "\"Line"
- actual
- Which is: "actual \"string\""
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mNonfatalFailureTest.EscapesStringOperands
-\e[0;32m[ RUN ] \e[mNonfatalFailureTest.DiffForLongStrings
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- golden_str
- Which is: "\"Line\0 1\"\nLine 2"
- "Line 2"
-With diff:
-@@ -1,2 @@
--\"Line\0 1\"
- Line 2
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mNonfatalFailureTest.DiffForLongStrings
-\e[0;32m[----------] \e[m3 tests from FatalFailureTest
-\e[0;32m[ RUN ] \e[mFatalFailureTest.FatalFailureInSubroutine
-(expecting a failure that x should be 1)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- x
- Which is: 2
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mFatalFailureTest.FatalFailureInSubroutine
-\e[0;32m[ RUN ] \e[mFatalFailureTest.FatalFailureInNestedSubroutine
-(expecting a failure that x should be 1)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- x
- Which is: 2
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mFatalFailureTest.FatalFailureInNestedSubroutine
-\e[0;32m[ RUN ] \e[mFatalFailureTest.NonfatalFailureInSubroutine
-(expecting a failure on false)
-googletest-output-test_.cc:#: Failure
-Value of: false
- Actual: false
-Expected: true
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mFatalFailureTest.NonfatalFailureInSubroutine
-\e[0;32m[----------] \e[m1 test from LoggingTest
-\e[0;32m[ RUN ] \e[mLoggingTest.InterleavingLoggingAndAssertions
-(expecting 2 failures on (3) >= (a[i]))
-i == 0
-i == 1
-googletest-output-test_.cc:#: Failure
-Expected: (3) >= (a[i]), actual: 3 vs 9
-Stack trace: (omitted)
-
-i == 2
-i == 3
-googletest-output-test_.cc:#: Failure
-Expected: (3) >= (a[i]), actual: 3 vs 6
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mLoggingTest.InterleavingLoggingAndAssertions
-\e[0;32m[----------] \e[m7 tests from SCOPED_TRACETest
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.AcceptedValues
-googletest-output-test_.cc:#: Failure
-Failed
-Just checking that all these values work fine.
-Google Test trace:
-googletest-output-test_.cc:#: (null)
-googletest-output-test_.cc:#: 1337
-googletest-output-test_.cc:#: std::string
-googletest-output-test_.cc:#: literal string
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.AcceptedValues
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.ObeysScopes
-(expected to fail)
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and shouldn't have a trace.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and should have a trace.
-Google Test trace:
-googletest-output-test_.cc:#: Expected trace
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and shouldn't have a trace.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.ObeysScopes
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.WorksInLoop
-(expected to fail)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 2
- n
- Which is: 1
-Google Test trace:
-googletest-output-test_.cc:#: i = 1
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- n
- Which is: 2
-Google Test trace:
-googletest-output-test_.cc:#: i = 2
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.WorksInLoop
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.WorksInSubroutine
-(expected to fail)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 2
- n
- Which is: 1
-Google Test trace:
-googletest-output-test_.cc:#: n = 1
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- n
- Which is: 2
-Google Test trace:
-googletest-output-test_.cc:#: n = 2
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.WorksInSubroutine
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.CanBeNested
-(expected to fail)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- n
- Which is: 2
-Google Test trace:
-googletest-output-test_.cc:#: n = 2
-googletest-output-test_.cc:#:
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.CanBeNested
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.CanBeRepeated
-(expected to fail)
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and should contain trace point A.
-Google Test trace:
-googletest-output-test_.cc:#: A
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and should contain trace point A and B.
-Google Test trace:
-googletest-output-test_.cc:#: B
-googletest-output-test_.cc:#: A
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and should contain trace point A, B, and C.
-Google Test trace:
-googletest-output-test_.cc:#: C
-googletest-output-test_.cc:#: B
-googletest-output-test_.cc:#: A
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-This failure is expected, and should contain trace point A, B, and D.
-Google Test trace:
-googletest-output-test_.cc:#: D
-googletest-output-test_.cc:#: B
-googletest-output-test_.cc:#: A
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.CanBeRepeated
-\e[0;32m[ RUN ] \e[mSCOPED_TRACETest.WorksConcurrently
-(expecting 6 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #1 (in thread B, only trace B alive).
-Google Test trace:
-googletest-output-test_.cc:#: Trace B
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #2 (in thread A, trace A & B both alive).
-Google Test trace:
-googletest-output-test_.cc:#: Trace A
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #3 (in thread B, trace A & B both alive).
-Google Test trace:
-googletest-output-test_.cc:#: Trace B
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #4 (in thread B, only trace A alive).
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #5 (in thread A, only trace A alive).
-Google Test trace:
-googletest-output-test_.cc:#: Trace A
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #6 (in thread A, no trace alive).
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.WorksConcurrently
-\e[0;32m[----------] \e[m1 test from ScopedTraceTest
-\e[0;32m[ RUN ] \e[mScopedTraceTest.WithExplicitFileAndLine
-googletest-output-test_.cc:#: Failure
-Failed
-Check that the trace is attached to a particular location.
-Google Test trace:
-explicit_file.cc:123: expected trace message
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mScopedTraceTest.WithExplicitFileAndLine
-\e[0;32m[----------] \e[m1 test from NonFatalFailureInFixtureConstructorTest
-\e[0;32m[ RUN ] \e[mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
-(expecting 5 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #1, in the test fixture c'tor.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #2, in SetUp().
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #3, in the test body.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #4, in TearDown.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #5, in the test fixture d'tor.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
-\e[0;32m[----------] \e[m1 test from FatalFailureInFixtureConstructorTest
-\e[0;32m[ RUN ] \e[mFatalFailureInFixtureConstructorTest.FailureInConstructor
-(expecting 2 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #1, in the test fixture c'tor.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #2, in the test fixture d'tor.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mFatalFailureInFixtureConstructorTest.FailureInConstructor
-\e[0;32m[----------] \e[m1 test from NonFatalFailureInSetUpTest
-\e[0;32m[ RUN ] \e[mNonFatalFailureInSetUpTest.FailureInSetUp
-(expecting 4 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #1, in SetUp().
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #2, in the test function.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #3, in TearDown().
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #4, in the test fixture d'tor.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mNonFatalFailureInSetUpTest.FailureInSetUp
-\e[0;32m[----------] \e[m1 test from FatalFailureInSetUpTest
-\e[0;32m[ RUN ] \e[mFatalFailureInSetUpTest.FailureInSetUp
-(expecting 3 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #1, in SetUp().
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #2, in TearDown().
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected failure #3, in the test fixture d'tor.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mFatalFailureInSetUpTest.FailureInSetUp
-\e[0;32m[----------] \e[m1 test from AddFailureAtTest
-\e[0;32m[ RUN ] \e[mAddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
-foo.cc:42: Failure
-Failed
-Expected nonfatal failure in foo.cc
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mAddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
-\e[0;32m[----------] \e[m1 test from GtestFailAtTest
-\e[0;32m[ RUN ] \e[mGtestFailAtTest.MessageContainsSpecifiedFileAndLineNumber
-foo.cc:42: Failure
-Failed
-Expected fatal failure in foo.cc
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mGtestFailAtTest.MessageContainsSpecifiedFileAndLineNumber
-\e[0;32m[----------] \e[m4 tests from MixedUpTestSuiteTest
-\e[0;32m[ RUN ] \e[mMixedUpTestSuiteTest.FirstTestFromNamespaceFoo
-\e[0;32m[ OK ] \e[mMixedUpTestSuiteTest.FirstTestFromNamespaceFoo
-\e[0;32m[ RUN ] \e[mMixedUpTestSuiteTest.SecondTestFromNamespaceFoo
-\e[0;32m[ OK ] \e[mMixedUpTestSuiteTest.SecondTestFromNamespaceFoo
-\e[0;32m[ RUN ] \e[mMixedUpTestSuiteTest.ThisShouldFail
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class. However, in test suite MixedUpTestSuiteTest,
-you defined test FirstTestFromNamespaceFoo and test ThisShouldFail
-using two different test fixture classes. This can happen if
-the two classes are from different namespaces or translation
-units and have the same name. You should probably rename one
-of the classes to put the tests into different test suites.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mMixedUpTestSuiteTest.ThisShouldFail
-\e[0;32m[ RUN ] \e[mMixedUpTestSuiteTest.ThisShouldFailToo
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class. However, in test suite MixedUpTestSuiteTest,
-you defined test FirstTestFromNamespaceFoo and test ThisShouldFailToo
-using two different test fixture classes. This can happen if
-the two classes are from different namespaces or translation
-units and have the same name. You should probably rename one
-of the classes to put the tests into different test suites.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mMixedUpTestSuiteTest.ThisShouldFailToo
-\e[0;32m[----------] \e[m2 tests from MixedUpTestSuiteWithSameTestNameTest
-\e[0;32m[ RUN ] \e[mMixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
-\e[0;32m[ OK ] \e[mMixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
-\e[0;32m[ RUN ] \e[mMixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class. However, in test suite MixedUpTestSuiteWithSameTestNameTest,
-you defined test TheSecondTestWithThisNameShouldFail and test TheSecondTestWithThisNameShouldFail
-using two different test fixture classes. This can happen if
-the two classes are from different namespaces or translation
-units and have the same name. You should probably rename one
-of the classes to put the tests into different test suites.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mMixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
-\e[0;32m[----------] \e[m2 tests from TEST_F_before_TEST_in_same_test_case
-\e[0;32m[ RUN ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
-\e[0;32m[ OK ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTEST_F
-\e[0;32m[ RUN ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class, so mixing TEST_F and TEST in the same test suite is
-illegal. In test suite TEST_F_before_TEST_in_same_test_case,
-test DefinedUsingTEST_F is defined using TEST_F but
-test DefinedUsingTESTAndShouldFail is defined using TEST. You probably
-want to change the TEST to TEST_F or move it to another test
-case.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
-\e[0;32m[----------] \e[m2 tests from TEST_before_TEST_F_in_same_test_case
-\e[0;32m[ RUN ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
-\e[0;32m[ OK ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST
-\e[0;32m[ RUN ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class, so mixing TEST_F and TEST in the same test suite is
-illegal. In test suite TEST_before_TEST_F_in_same_test_case,
-test DefinedUsingTEST_FAndShouldFail is defined using TEST_F but
-test DefinedUsingTEST is defined using TEST. You probably
-want to change the TEST to TEST_F or move it to another test
-case.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
-\e[0;32m[----------] \e[m8 tests from ExpectNonfatalFailureTest
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.CanReferenceGlobalVariables
-\e[0;32m[ OK ] \e[mExpectNonfatalFailureTest.CanReferenceGlobalVariables
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.CanReferenceLocalVariables
-\e[0;32m[ OK ] \e[mExpectNonfatalFailureTest.CanReferenceLocalVariables
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
-\e[0;32m[ OK ] \e[mExpectNonfatalFailureTest.SucceedsWhenThereIsOneNonfatalFailure
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual: 2 failures
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure 1.
-Stack trace: (omitted)
-
-
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure 2.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual:
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.FailsWhenStatementReturns
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenStatementReturns
-\e[0;32m[ RUN ] \e[mExpectNonfatalFailureTest.FailsWhenStatementThrows
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenStatementThrows
-\e[0;32m[----------] \e[m8 tests from ExpectFatalFailureTest
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.CanReferenceGlobalVariables
-\e[0;32m[ OK ] \e[mExpectFatalFailureTest.CanReferenceGlobalVariables
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.CanReferenceLocalStaticVariables
-\e[0;32m[ OK ] \e[mExpectFatalFailureTest.CanReferenceLocalStaticVariables
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
-\e[0;32m[ OK ] \e[mExpectFatalFailureTest.SucceedsWhenThereIsOneFatalFailure
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual: 2 failures
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual:
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.FailsWhenStatementReturns
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenStatementReturns
-\e[0;32m[ RUN ] \e[mExpectFatalFailureTest.FailsWhenStatementThrows
-(expecting a failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenStatementThrows
-\e[0;32m[----------] \e[m2 tests from TypedTest/0, where TypeParam = int
-\e[0;32m[ RUN ] \e[mTypedTest/0.Success
-\e[0;32m[ OK ] \e[mTypedTest/0.Success
-\e[0;32m[ RUN ] \e[mTypedTest/0.Failure
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- TypeParam()
- Which is: 0
-Expected failure
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mTypedTest/0.Failure, where TypeParam = int
-\e[0;32m[----------] \e[m2 tests from TypedTestWithNames/char0, where TypeParam = char
-\e[0;32m[ RUN ] \e[mTypedTestWithNames/char0.Success
-\e[0;32m[ OK ] \e[mTypedTestWithNames/char0.Success
-\e[0;32m[ RUN ] \e[mTypedTestWithNames/char0.Failure
-googletest-output-test_.cc:#: Failure
-Failed
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mTypedTestWithNames/char0.Failure, where TypeParam = char
-\e[0;32m[----------] \e[m2 tests from TypedTestWithNames/int1, where TypeParam = int
-\e[0;32m[ RUN ] \e[mTypedTestWithNames/int1.Success
-\e[0;32m[ OK ] \e[mTypedTestWithNames/int1.Success
-\e[0;32m[ RUN ] \e[mTypedTestWithNames/int1.Failure
-googletest-output-test_.cc:#: Failure
-Failed
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mTypedTestWithNames/int1.Failure, where TypeParam = int
-\e[0;32m[----------] \e[m2 tests from Unsigned/TypedTestP/0, where TypeParam = unsigned char
-\e[0;32m[ RUN ] \e[mUnsigned/TypedTestP/0.Success
-\e[0;32m[ OK ] \e[mUnsigned/TypedTestP/0.Success
-\e[0;32m[ RUN ] \e[mUnsigned/TypedTestP/0.Failure
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1U
- Which is: 1
- TypeParam()
- Which is: '\0'
-Expected failure
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mUnsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
-\e[0;32m[----------] \e[m2 tests from Unsigned/TypedTestP/1, where TypeParam = unsigned int
-\e[0;32m[ RUN ] \e[mUnsigned/TypedTestP/1.Success
-\e[0;32m[ OK ] \e[mUnsigned/TypedTestP/1.Success
-\e[0;32m[ RUN ] \e[mUnsigned/TypedTestP/1.Failure
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1U
- Which is: 1
- TypeParam()
- Which is: 0
-Expected failure
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mUnsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
-\e[0;32m[----------] \e[m2 tests from UnsignedCustomName/TypedTestP/unsignedChar0, where TypeParam = unsigned char
-\e[0;32m[ RUN ] \e[mUnsignedCustomName/TypedTestP/unsignedChar0.Success
-\e[0;32m[ OK ] \e[mUnsignedCustomName/TypedTestP/unsignedChar0.Success
-\e[0;32m[ RUN ] \e[mUnsignedCustomName/TypedTestP/unsignedChar0.Failure
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1U
- Which is: 1
- TypeParam()
- Which is: '\0'
-Expected failure
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mUnsignedCustomName/TypedTestP/unsignedChar0.Failure, where TypeParam = unsigned char
-\e[0;32m[----------] \e[m2 tests from UnsignedCustomName/TypedTestP/unsignedInt1, where TypeParam = unsigned int
-\e[0;32m[ RUN ] \e[mUnsignedCustomName/TypedTestP/unsignedInt1.Success
-\e[0;32m[ OK ] \e[mUnsignedCustomName/TypedTestP/unsignedInt1.Success
-\e[0;32m[ RUN ] \e[mUnsignedCustomName/TypedTestP/unsignedInt1.Failure
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1U
- Which is: 1
- TypeParam()
- Which is: 0
-Expected failure
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mUnsignedCustomName/TypedTestP/unsignedInt1.Failure, where TypeParam = unsigned int
-\e[0;32m[----------] \e[m4 tests from ExpectFailureTest
-\e[0;32m[ RUN ] \e[mExpectFailureTest.ExpectFatalFailure
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual:
-googletest-output-test_.cc:#: Success:
-Succeeded
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual:
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure containing "Some other fatal failure expected."
- Actual:
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectFatalFailure
-\e[0;32m[ RUN ] \e[mExpectFailureTest.ExpectNonFatalFailure
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual:
-googletest-output-test_.cc:#: Success:
-Succeeded
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual:
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure containing "Some other non-fatal failure."
- Actual:
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectNonFatalFailure
-\e[0;32m[ RUN ] \e[mExpectFailureTest.ExpectFatalFailureOnAllThreads
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual:
-googletest-output-test_.cc:#: Success:
-Succeeded
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual:
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 fatal failure containing "Some other fatal failure expected."
- Actual:
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectFatalFailureOnAllThreads
-\e[0;32m[ RUN ] \e[mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual:
-googletest-output-test_.cc:#: Success:
-Succeeded
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual:
-googletest-output-test_.cc:#: Fatal failure:
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-(expecting 1 failure)
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure containing "Some other non-fatal failure."
- Actual:
-googletest-output-test_.cc:#: Non-fatal failure:
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
-\e[0;32m[----------] \e[m2 tests from ExpectFailureWithThreadsTest
-\e[0;32m[ RUN ] \e[mExpectFailureWithThreadsTest.ExpectFatalFailure
-(expecting 2 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-gtest.cc:#: Failure
-Expected: 1 fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFailureWithThreadsTest.ExpectFatalFailure
-\e[0;32m[ RUN ] \e[mExpectFailureWithThreadsTest.ExpectNonFatalFailure
-(expecting 2 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-gtest.cc:#: Failure
-Expected: 1 non-fatal failure
- Actual: 0 failures
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mExpectFailureWithThreadsTest.ExpectNonFatalFailure
-\e[0;32m[----------] \e[m1 test from ScopedFakeTestPartResultReporterTest
-\e[0;32m[ RUN ] \e[mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
-(expecting 2 failures)
-googletest-output-test_.cc:#: Failure
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-googletest-output-test_.cc:#: Failure
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
-\e[0;32m[----------] \e[m2 tests from DynamicFixture
-DynamicFixture::SetUpTestSuite
-\e[0;32m[ RUN ] \e[mDynamicFixture.DynamicTestPass
-DynamicFixture()
-DynamicFixture::SetUp
-DynamicFixture::TearDown
-~DynamicFixture()
-\e[0;32m[ OK ] \e[mDynamicFixture.DynamicTestPass
-\e[0;32m[ RUN ] \e[mDynamicFixture.DynamicTestFail
-DynamicFixture()
-DynamicFixture::SetUp
-googletest-output-test_.cc:#: Failure
-Value of: Pass
- Actual: false
-Expected: true
-Stack trace: (omitted)
-
-DynamicFixture::TearDown
-~DynamicFixture()
-\e[0;31m[ FAILED ] \e[mDynamicFixture.DynamicTestFail
-DynamicFixture::TearDownTestSuite
-\e[0;32m[----------] \e[m1 test from DynamicFixtureAnotherName
-DynamicFixture::SetUpTestSuite
-\e[0;32m[ RUN ] \e[mDynamicFixtureAnotherName.DynamicTestPass
-DynamicFixture()
-DynamicFixture::SetUp
-DynamicFixture::TearDown
-~DynamicFixture()
-\e[0;32m[ OK ] \e[mDynamicFixtureAnotherName.DynamicTestPass
-DynamicFixture::TearDownTestSuite
-\e[0;32m[----------] \e[m2 tests from BadDynamicFixture1
-DynamicFixture::SetUpTestSuite
-\e[0;32m[ RUN ] \e[mBadDynamicFixture1.FixtureBase
-DynamicFixture()
-DynamicFixture::SetUp
-DynamicFixture::TearDown
-~DynamicFixture()
-\e[0;32m[ OK ] \e[mBadDynamicFixture1.FixtureBase
-\e[0;32m[ RUN ] \e[mBadDynamicFixture1.TestBase
-DynamicFixture()
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class, so mixing TEST_F and TEST in the same test suite is
-illegal. In test suite BadDynamicFixture1,
-test FixtureBase is defined using TEST_F but
-test TestBase is defined using TEST. You probably
-want to change the TEST to TEST_F or move it to another test
-case.
-Stack trace: (omitted)
-
-~DynamicFixture()
-\e[0;31m[ FAILED ] \e[mBadDynamicFixture1.TestBase
-DynamicFixture::TearDownTestSuite
-\e[0;32m[----------] \e[m2 tests from BadDynamicFixture2
-DynamicFixture::SetUpTestSuite
-\e[0;32m[ RUN ] \e[mBadDynamicFixture2.FixtureBase
-DynamicFixture()
-DynamicFixture::SetUp
-DynamicFixture::TearDown
-~DynamicFixture()
-\e[0;32m[ OK ] \e[mBadDynamicFixture2.FixtureBase
-\e[0;32m[ RUN ] \e[mBadDynamicFixture2.Derived
-DynamicFixture()
-gtest.cc:#: Failure
-Failed
-All tests in the same test suite must use the same test fixture
-class. However, in test suite BadDynamicFixture2,
-you defined test FixtureBase and test Derived
-using two different test fixture classes. This can happen if
-the two classes are from different namespaces or translation
-units and have the same name. You should probably rename one
-of the classes to put the tests into different test suites.
-Stack trace: (omitted)
-
-~DynamicFixture()
-\e[0;31m[ FAILED ] \e[mBadDynamicFixture2.Derived
-DynamicFixture::TearDownTestSuite
-\e[0;32m[----------] \e[m1 test from PrintingFailingParams/FailingParamTest
-\e[0;32m[ RUN ] \e[mPrintingFailingParams/FailingParamTest.Fails/0
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- GetParam()
- Which is: 2
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mPrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
-\e[0;32m[----------] \e[m1 test from EmptyBasenameParamInst
-\e[0;32m[ RUN ] \e[mEmptyBasenameParamInst.Passes/0
-\e[0;32m[ OK ] \e[mEmptyBasenameParamInst.Passes/0
-\e[0;32m[----------] \e[m2 tests from PrintingStrings/ParamTest
-\e[0;32m[ RUN ] \e[mPrintingStrings/ParamTest.Success/a
-\e[0;32m[ OK ] \e[mPrintingStrings/ParamTest.Success/a
-\e[0;32m[ RUN ] \e[mPrintingStrings/ParamTest.Failure/a
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- "b"
- GetParam()
- Which is: "a"
-Expected failure
-Stack trace: (omitted)
-
-\e[0;31m[ FAILED ] \e[mPrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
-\e[0;32m[----------] \e[mGlobal test environment tear-down
-BarEnvironment::TearDown() called.
-googletest-output-test_.cc:#: Failure
-Failed
-Expected non-fatal failure.
-Stack trace: (omitted)
-
-FooEnvironment::TearDown() called.
-googletest-output-test_.cc:#: Failure
-Failed
-Expected fatal failure.
-Stack trace: (omitted)
-
-\e[0;32m[==========] \e[m85 tests from 40 test suites ran.
-\e[0;32m[ PASSED ] \e[m31 tests.
-\e[0;31m[ FAILED ] \e[m54 tests, listed below:
-\e[0;31m[ FAILED ] \e[mNonfatalFailureTest.EscapesStringOperands
-\e[0;31m[ FAILED ] \e[mNonfatalFailureTest.DiffForLongStrings
-\e[0;31m[ FAILED ] \e[mFatalFailureTest.FatalFailureInSubroutine
-\e[0;31m[ FAILED ] \e[mFatalFailureTest.FatalFailureInNestedSubroutine
-\e[0;31m[ FAILED ] \e[mFatalFailureTest.NonfatalFailureInSubroutine
-\e[0;31m[ FAILED ] \e[mLoggingTest.InterleavingLoggingAndAssertions
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.AcceptedValues
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.ObeysScopes
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.WorksInLoop
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.WorksInSubroutine
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.CanBeNested
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.CanBeRepeated
-\e[0;31m[ FAILED ] \e[mSCOPED_TRACETest.WorksConcurrently
-\e[0;31m[ FAILED ] \e[mScopedTraceTest.WithExplicitFileAndLine
-\e[0;31m[ FAILED ] \e[mNonFatalFailureInFixtureConstructorTest.FailureInConstructor
-\e[0;31m[ FAILED ] \e[mFatalFailureInFixtureConstructorTest.FailureInConstructor
-\e[0;31m[ FAILED ] \e[mNonFatalFailureInSetUpTest.FailureInSetUp
-\e[0;31m[ FAILED ] \e[mFatalFailureInSetUpTest.FailureInSetUp
-\e[0;31m[ FAILED ] \e[mAddFailureAtTest.MessageContainsSpecifiedFileAndLineNumber
-\e[0;31m[ FAILED ] \e[mGtestFailAtTest.MessageContainsSpecifiedFileAndLineNumber
-\e[0;31m[ FAILED ] \e[mMixedUpTestSuiteTest.ThisShouldFail
-\e[0;31m[ FAILED ] \e[mMixedUpTestSuiteTest.ThisShouldFailToo
-\e[0;31m[ FAILED ] \e[mMixedUpTestSuiteWithSameTestNameTest.TheSecondTestWithThisNameShouldFail
-\e[0;31m[ FAILED ] \e[mTEST_F_before_TEST_in_same_test_case.DefinedUsingTESTAndShouldFail
-\e[0;31m[ FAILED ] \e[mTEST_before_TEST_F_in_same_test_case.DefinedUsingTEST_FAndShouldFail
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsNoNonfatalFailure
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenThereAreTwoNonfatalFailures
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenThereIsOneFatalFailure
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenStatementReturns
-\e[0;31m[ FAILED ] \e[mExpectNonfatalFailureTest.FailsWhenStatementThrows
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenThereIsNoFatalFailure
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenThereAreTwoFatalFailures
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenThereIsOneNonfatalFailure
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenStatementReturns
-\e[0;31m[ FAILED ] \e[mExpectFatalFailureTest.FailsWhenStatementThrows
-\e[0;31m[ FAILED ] \e[mTypedTest/0.Failure, where TypeParam = int
-\e[0;31m[ FAILED ] \e[mTypedTestWithNames/char0.Failure, where TypeParam = char
-\e[0;31m[ FAILED ] \e[mTypedTestWithNames/int1.Failure, where TypeParam = int
-\e[0;31m[ FAILED ] \e[mUnsigned/TypedTestP/0.Failure, where TypeParam = unsigned char
-\e[0;31m[ FAILED ] \e[mUnsigned/TypedTestP/1.Failure, where TypeParam = unsigned int
-\e[0;31m[ FAILED ] \e[mUnsignedCustomName/TypedTestP/unsignedChar0.Failure, where TypeParam = unsigned char
-\e[0;31m[ FAILED ] \e[mUnsignedCustomName/TypedTestP/unsignedInt1.Failure, where TypeParam = unsigned int
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectFatalFailure
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectNonFatalFailure
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectFatalFailureOnAllThreads
-\e[0;31m[ FAILED ] \e[mExpectFailureTest.ExpectNonFatalFailureOnAllThreads
-\e[0;31m[ FAILED ] \e[mExpectFailureWithThreadsTest.ExpectFatalFailure
-\e[0;31m[ FAILED ] \e[mExpectFailureWithThreadsTest.ExpectNonFatalFailure
-\e[0;31m[ FAILED ] \e[mScopedFakeTestPartResultReporterTest.InterceptOnlyCurrentThread
-\e[0;31m[ FAILED ] \e[mDynamicFixture.DynamicTestFail
-\e[0;31m[ FAILED ] \e[mBadDynamicFixture1.TestBase
-\e[0;31m[ FAILED ] \e[mBadDynamicFixture2.Derived
-\e[0;31m[ FAILED ] \e[mPrintingFailingParams/FailingParamTest.Fails/0, where GetParam() = 2
-\e[0;31m[ FAILED ] \e[mPrintingStrings/ParamTest.Failure/a, where GetParam() = "a"
-
-54 FAILED TESTS
-\e[0;33m YOU HAVE 1 DISABLED TEST
-
-\e[mNote: Google Test filter = FatalFailureTest.*:LoggingTest.*
-[==========] Running 4 tests from 2 test suites.
-[----------] Global test environment set-up.
-[----------] 3 tests from FatalFailureTest
-[ RUN ] FatalFailureTest.FatalFailureInSubroutine
-(expecting a failure that x should be 1)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- x
- Which is: 2
-Stack trace: (omitted)
-
-[ FAILED ] FatalFailureTest.FatalFailureInSubroutine (? ms)
-[ RUN ] FatalFailureTest.FatalFailureInNestedSubroutine
-(expecting a failure that x should be 1)
-googletest-output-test_.cc:#: Failure
-Expected equality of these values:
- 1
- x
- Which is: 2
-Stack trace: (omitted)
-
-[ FAILED ] FatalFailureTest.FatalFailureInNestedSubroutine (? ms)
-[ RUN ] FatalFailureTest.NonfatalFailureInSubroutine
-(expecting a failure on false)
-googletest-output-test_.cc:#: Failure
-Value of: false
- Actual: false
-Expected: true
-Stack trace: (omitted)
-
-[ FAILED ] FatalFailureTest.NonfatalFailureInSubroutine (? ms)
-[----------] 3 tests from FatalFailureTest (? ms total)
-
-[----------] 1 test from LoggingTest
-[ RUN ] LoggingTest.InterleavingLoggingAndAssertions
-(expecting 2 failures on (3) >= (a[i]))
-i == 0
-i == 1
-googletest-output-test_.cc:#: Failure
-Expected: (3) >= (a[i]), actual: 3 vs 9
-Stack trace: (omitted)
-
-i == 2
-i == 3
-googletest-output-test_.cc:#: Failure
-Expected: (3) >= (a[i]), actual: 3 vs 6
-Stack trace: (omitted)
-
-[ FAILED ] LoggingTest.InterleavingLoggingAndAssertions (? ms)
-[----------] 1 test from LoggingTest (? ms total)
-
-[----------] Global test environment tear-down
-[==========] 4 tests from 2 test suites ran. (? ms total)
-[ PASSED ] 0 tests.
-[ FAILED ] 4 tests, listed below:
-[ FAILED ] FatalFailureTest.FatalFailureInSubroutine
-[ FAILED ] FatalFailureTest.FatalFailureInNestedSubroutine
-[ FAILED ] FatalFailureTest.NonfatalFailureInSubroutine
-[ FAILED ] LoggingTest.InterleavingLoggingAndAssertions
-
- 4 FAILED TESTS
-Note: Google Test filter = *DISABLED_*
-[==========] Running 1 test from 1 test suite.
-[----------] Global test environment set-up.
-[----------] 1 test from DisabledTestsWarningTest
-[ RUN ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
-[ OK ] DisabledTestsWarningTest.DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning
-[----------] Global test environment tear-down
-[==========] 1 test from 1 test suite ran.
-[ PASSED ] 1 test.
-Note: Google Test filter = PassingTest.*
-Note: This is test shard 2 of 2.
-[==========] Running 1 test from 1 test suite.
-[----------] Global test environment set-up.
-[----------] 1 test from PassingTest
-[ RUN ] PassingTest.PassingTest2
-[ OK ] PassingTest.PassingTest2
-[----------] Global test environment tear-down
-[==========] 1 test from 1 test suite ran.
-[ PASSED ] 1 test.
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests the text output of Google C++ Testing and Mocking Framework.
-
-To update the golden file:
-googletest_output_test.py --build_dir=BUILD/DIR --gengolden
-where BUILD/DIR contains the built googletest-output-test_ file.
-googletest_output_test.py --gengolden
-googletest_output_test.py
-"""
-
-import difflib
-import os
-import re
-import sys
-import gtest_test_utils
-
-
-# The flag for generating the golden file
-GENGOLDEN_FLAG = '--gengolden'
-CATCH_EXCEPTIONS_ENV_VAR_NAME = 'GTEST_CATCH_EXCEPTIONS'
-
-# The flag indicating stacktraces are not supported
-NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support'
-
-IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
-IS_WINDOWS = os.name == 'nt'
-
-GOLDEN_NAME = 'googletest-output-test-golden-lin.txt'
-
-PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('googletest-output-test_')
-
-# At least one command we exercise must not have the
-# 'internal_skip_environment_and_ad_hoc_tests' argument.
-COMMAND_LIST_TESTS = ({}, [PROGRAM_PATH, '--gtest_list_tests'])
-COMMAND_WITH_COLOR = ({}, [PROGRAM_PATH, '--gtest_color=yes'])
-COMMAND_WITH_TIME = ({}, [PROGRAM_PATH,
- '--gtest_print_time',
- 'internal_skip_environment_and_ad_hoc_tests',
- '--gtest_filter=FatalFailureTest.*:LoggingTest.*'])
-COMMAND_WITH_DISABLED = (
- {}, [PROGRAM_PATH,
- '--gtest_also_run_disabled_tests',
- 'internal_skip_environment_and_ad_hoc_tests',
- '--gtest_filter=*DISABLED_*'])
-COMMAND_WITH_SHARDING = (
- {'GTEST_SHARD_INDEX': '1', 'GTEST_TOTAL_SHARDS': '2'},
- [PROGRAM_PATH,
- 'internal_skip_environment_and_ad_hoc_tests',
- '--gtest_filter=PassingTest.*'])
-
-GOLDEN_PATH = os.path.join(gtest_test_utils.GetSourceDir(), GOLDEN_NAME)
-
-
-def ToUnixLineEnding(s):
- """Changes all Windows/Mac line endings in s to UNIX line endings."""
-
- return s.replace('\r\n', '\n').replace('\r', '\n')
-
-
-def RemoveLocations(test_output):
- """Removes all file location info from a Google Test program's output.
-
- Args:
- test_output: the output of a Google Test program.
-
- Returns:
- output with all file location info (in the form of
- 'DIRECTORY/FILE_NAME:LINE_NUMBER: 'or
- 'DIRECTORY\\FILE_NAME(LINE_NUMBER): ') replaced by
- 'FILE_NAME:#: '.
- """
-
- return re.sub(r'.*[/\\]((googletest-output-test_|gtest).cc)(\:\d+|\(\d+\))\: ',
- r'\1:#: ', test_output)
-
-
-def RemoveStackTraceDetails(output):
- """Removes all stack traces from a Google Test program's output."""
-
- # *? means "find the shortest string that matches".
- return re.sub(r'Stack trace:(.|\n)*?\n\n',
- 'Stack trace: (omitted)\n\n', output)
-
-
-def RemoveStackTraces(output):
- """Removes all traces of stack traces from a Google Test program's output."""
-
- # *? means "find the shortest string that matches".
- return re.sub(r'Stack trace:(.|\n)*?\n\n', '', output)
-
-
-def RemoveTime(output):
- """Removes all time information from a Google Test program's output."""
-
- return re.sub(r'\(\d+ ms', '(? ms', output)
-
-
-def RemoveTypeInfoDetails(test_output):
- """Removes compiler-specific type info from Google Test program's output.
-
- Args:
- test_output: the output of a Google Test program.
-
- Returns:
- output with type information normalized to canonical form.
- """
-
- # some compilers output the name of type 'unsigned int' as 'unsigned'
- return re.sub(r'unsigned int', 'unsigned', test_output)
-
-
-def NormalizeToCurrentPlatform(test_output):
- """Normalizes platform specific output details for easier comparison."""
-
- if IS_WINDOWS:
- # Removes the color information that is not present on Windows.
- test_output = re.sub('\x1b\\[(0;3\d)?m', '', test_output)
- # Changes failure message headers into the Windows format.
- test_output = re.sub(r': Failure\n', r': error: ', test_output)
- # Changes file(line_number) to file:line_number.
- test_output = re.sub(r'((\w|\.)+)\((\d+)\):', r'\1:\3:', test_output)
-
- return test_output
-
-
-def RemoveTestCounts(output):
- """Removes test counts from a Google Test program's output."""
-
- output = re.sub(r'\d+ tests?, listed below',
- '? tests, listed below', output)
- output = re.sub(r'\d+ FAILED TESTS',
- '? FAILED TESTS', output)
- output = re.sub(r'\d+ tests? from \d+ test cases?',
- '? tests from ? test cases', output)
- output = re.sub(r'\d+ tests? from ([a-zA-Z_])',
- r'? tests from \1', output)
- return re.sub(r'\d+ tests?\.', '? tests.', output)
-
-
-def RemoveMatchingTests(test_output, pattern):
- """Removes output of specified tests from a Google Test program's output.
-
- This function strips not only the beginning and the end of a test but also
- all output in between.
-
- Args:
- test_output: A string containing the test output.
- pattern: A regex string that matches names of test cases or
- tests to remove.
-
- Returns:
- Contents of test_output with tests whose names match pattern removed.
- """
-
- test_output = re.sub(
- r'.*\[ RUN \] .*%s(.|\n)*?\[( FAILED | OK )\] .*%s.*\n' % (
- pattern, pattern),
- '',
- test_output)
- return re.sub(r'.*%s.*\n' % pattern, '', test_output)
-
-
-def NormalizeOutput(output):
- """Normalizes output (the output of googletest-output-test_.exe)."""
-
- output = ToUnixLineEnding(output)
- output = RemoveLocations(output)
- output = RemoveStackTraceDetails(output)
- output = RemoveTime(output)
- return output
-
-
-def GetShellCommandOutput(env_cmd):
- """Runs a command in a sub-process, and returns its output in a string.
-
- Args:
- env_cmd: The shell command. A 2-tuple where element 0 is a dict of extra
- environment variables to set, and element 1 is a string with
- the command and any flags.
-
- Returns:
- A string with the command's combined standard and diagnostic output.
- """
-
- # Spawns cmd in a sub-process, and gets its standard I/O file objects.
- # Set and save the environment properly.
- environ = os.environ.copy()
- environ.update(env_cmd[0])
- p = gtest_test_utils.Subprocess(env_cmd[1], env=environ)
-
- return p.output
-
-
-def GetCommandOutput(env_cmd):
- """Runs a command and returns its output with all file location
- info stripped off.
-
- Args:
- env_cmd: The shell command. A 2-tuple where element 0 is a dict of extra
- environment variables to set, and element 1 is a string with
- the command and any flags.
- """
-
- # Disables exception pop-ups on Windows.
- environ, cmdline = env_cmd
- environ = dict(environ) # Ensures we are modifying a copy.
- environ[CATCH_EXCEPTIONS_ENV_VAR_NAME] = '1'
- return NormalizeOutput(GetShellCommandOutput((environ, cmdline)))
-
-
-def GetOutputOfAllCommands():
- """Returns concatenated output from several representative commands."""
-
- return (GetCommandOutput(COMMAND_WITH_COLOR) +
- GetCommandOutput(COMMAND_WITH_TIME) +
- GetCommandOutput(COMMAND_WITH_DISABLED) +
- GetCommandOutput(COMMAND_WITH_SHARDING))
-
-
-test_list = GetShellCommandOutput(COMMAND_LIST_TESTS)
-SUPPORTS_DEATH_TESTS = 'DeathTest' in test_list
-SUPPORTS_TYPED_TESTS = 'TypedTest' in test_list
-SUPPORTS_THREADS = 'ExpectFailureWithThreadsTest' in test_list
-SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv
-
-CAN_GENERATE_GOLDEN_FILE = (SUPPORTS_DEATH_TESTS and
- SUPPORTS_TYPED_TESTS and
- SUPPORTS_THREADS and
- SUPPORTS_STACK_TRACES)
-
-class GTestOutputTest(gtest_test_utils.TestCase):
- def RemoveUnsupportedTests(self, test_output):
- if not SUPPORTS_DEATH_TESTS:
- test_output = RemoveMatchingTests(test_output, 'DeathTest')
- if not SUPPORTS_TYPED_TESTS:
- test_output = RemoveMatchingTests(test_output, 'TypedTest')
- test_output = RemoveMatchingTests(test_output, 'TypedDeathTest')
- test_output = RemoveMatchingTests(test_output, 'TypeParamDeathTest')
- if not SUPPORTS_THREADS:
- test_output = RemoveMatchingTests(test_output,
- 'ExpectFailureWithThreadsTest')
- test_output = RemoveMatchingTests(test_output,
- 'ScopedFakeTestPartResultReporterTest')
- test_output = RemoveMatchingTests(test_output,
- 'WorksConcurrently')
- if not SUPPORTS_STACK_TRACES:
- test_output = RemoveStackTraces(test_output)
-
- return test_output
-
- def testOutput(self):
- output = GetOutputOfAllCommands()
-
- golden_file = open(GOLDEN_PATH, 'rb')
- # A mis-configured source control system can cause \r appear in EOL
- # sequences when we read the golden file irrespective of an operating
- # system used. Therefore, we need to strip those \r's from newlines
- # unconditionally.
- golden = ToUnixLineEnding(golden_file.read().decode())
- golden_file.close()
-
- # We want the test to pass regardless of certain features being
- # supported or not.
-
- # We still have to remove type name specifics in all cases.
- normalized_actual = RemoveTypeInfoDetails(output)
- normalized_golden = RemoveTypeInfoDetails(golden)
-
- if CAN_GENERATE_GOLDEN_FILE:
- self.assertEqual(normalized_golden, normalized_actual,
- '\n'.join(difflib.unified_diff(
- normalized_golden.split('\n'),
- normalized_actual.split('\n'),
- 'golden', 'actual')))
- else:
- normalized_actual = NormalizeToCurrentPlatform(
- RemoveTestCounts(normalized_actual))
- normalized_golden = NormalizeToCurrentPlatform(
- RemoveTestCounts(self.RemoveUnsupportedTests(normalized_golden)))
-
- # This code is very handy when debugging golden file differences:
- if os.getenv('DEBUG_GTEST_OUTPUT_TEST'):
- open(os.path.join(
- gtest_test_utils.GetSourceDir(),
- '_googletest-output-test_normalized_actual.txt'), 'wb').write(
- normalized_actual)
- open(os.path.join(
- gtest_test_utils.GetSourceDir(),
- '_googletest-output-test_normalized_golden.txt'), 'wb').write(
- normalized_golden)
-
- self.assertEqual(normalized_golden, normalized_actual)
-
-
-if __name__ == '__main__':
- if NO_STACKTRACE_SUPPORT_FLAG in sys.argv:
- # unittest.main() can't handle unknown flags
- sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
-
- if GENGOLDEN_FLAG in sys.argv:
- if CAN_GENERATE_GOLDEN_FILE:
- output = GetOutputOfAllCommands()
- golden_file = open(GOLDEN_PATH, 'wb')
- golden_file.write(output)
- golden_file.close()
- else:
- message = (
- """Unable to write a golden file when compiled in an environment
-that does not support all the required features (death tests,
-typed tests, stack traces, and multiple threads).
-Please build this test and generate the golden file using Blaze on Linux.""")
-
- sys.stderr.write(message)
- sys.exit(1)
- else:
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// The purpose of this file is to generate Google Test output under
-// various conditions. The output will then be verified by
-// googletest-output-test.py to ensure that Google Test generates the
-// desired messages. Therefore, most tests in this file are MEANT TO
-// FAIL.
-
-#include "gtest/gtest-spi.h"
-#include "gtest/gtest.h"
-#include "src/gtest-internal-inl.h"
-
-#include <stdlib.h>
-
-#if _MSC_VER
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127 /* conditional expression is constant */)
-#endif // _MSC_VER
-
-#if GTEST_IS_THREADSAFE
-using testing::ScopedFakeTestPartResultReporter;
-using testing::TestPartResultArray;
-
-using testing::internal::Notification;
-using testing::internal::ThreadWithParam;
-#endif
-
-namespace posix = ::testing::internal::posix;
-
-// Tests catching fatal failures.
-
-// A subroutine used by the following test.
-void TestEq1(int x) {
- ASSERT_EQ(1, x);
-}
-
-// This function calls a test subroutine, catches the fatal failure it
-// generates, and then returns early.
-void TryTestSubroutine() {
- // Calls a subrountine that yields a fatal failure.
- TestEq1(2);
-
- // Catches the fatal failure and aborts the test.
- //
- // The testing::Test:: prefix is necessary when calling
- // HasFatalFailure() outside of a TEST, TEST_F, or test fixture.
- if (testing::Test::HasFatalFailure()) return;
-
- // If we get here, something is wrong.
- FAIL() << "This should never be reached.";
-}
-
-TEST(PassingTest, PassingTest1) {
-}
-
-TEST(PassingTest, PassingTest2) {
-}
-
-// Tests that parameters of failing parameterized tests are printed in the
-// failing test summary.
-class FailingParamTest : public testing::TestWithParam<int> {};
-
-TEST_P(FailingParamTest, Fails) {
- EXPECT_EQ(1, GetParam());
-}
-
-// This generates a test which will fail. Google Test is expected to print
-// its parameter when it outputs the list of all failed tests.
-INSTANTIATE_TEST_SUITE_P(PrintingFailingParams,
- FailingParamTest,
- testing::Values(2));
-
-// Tests that an empty value for the test suite basename yields just
-// the test name without any prior /
-class EmptyBasenameParamInst : public testing::TestWithParam<int> {};
-
-TEST_P(EmptyBasenameParamInst, Passes) { EXPECT_EQ(1, GetParam()); }
-
-INSTANTIATE_TEST_SUITE_P(, EmptyBasenameParamInst, testing::Values(1));
-
-static const char kGoldenString[] = "\"Line\0 1\"\nLine 2";
-
-TEST(NonfatalFailureTest, EscapesStringOperands) {
- std::string actual = "actual \"string\"";
- EXPECT_EQ(kGoldenString, actual);
-
- const char* golden = kGoldenString;
- EXPECT_EQ(golden, actual);
-}
-
-TEST(NonfatalFailureTest, DiffForLongStrings) {
- std::string golden_str(kGoldenString, sizeof(kGoldenString) - 1);
- EXPECT_EQ(golden_str, "Line 2");
-}
-
-// Tests catching a fatal failure in a subroutine.
-TEST(FatalFailureTest, FatalFailureInSubroutine) {
- printf("(expecting a failure that x should be 1)\n");
-
- TryTestSubroutine();
-}
-
-// Tests catching a fatal failure in a nested subroutine.
-TEST(FatalFailureTest, FatalFailureInNestedSubroutine) {
- printf("(expecting a failure that x should be 1)\n");
-
- // Calls a subrountine that yields a fatal failure.
- TryTestSubroutine();
-
- // Catches the fatal failure and aborts the test.
- //
- // When calling HasFatalFailure() inside a TEST, TEST_F, or test
- // fixture, the testing::Test:: prefix is not needed.
- if (HasFatalFailure()) return;
-
- // If we get here, something is wrong.
- FAIL() << "This should never be reached.";
-}
-
-// Tests HasFatalFailure() after a failed EXPECT check.
-TEST(FatalFailureTest, NonfatalFailureInSubroutine) {
- printf("(expecting a failure on false)\n");
- EXPECT_TRUE(false); // Generates a nonfatal failure
- ASSERT_FALSE(HasFatalFailure()); // This should succeed.
-}
-
-// Tests interleaving user logging and Google Test assertions.
-TEST(LoggingTest, InterleavingLoggingAndAssertions) {
- static const int a[4] = {
- 3, 9, 2, 6
- };
-
- printf("(expecting 2 failures on (3) >= (a[i]))\n");
- for (int i = 0; i < static_cast<int>(sizeof(a)/sizeof(*a)); i++) {
- printf("i == %d\n", i);
- EXPECT_GE(3, a[i]);
- }
-}
-
-// Tests the SCOPED_TRACE macro.
-
-// A helper function for testing SCOPED_TRACE.
-void SubWithoutTrace(int n) {
- EXPECT_EQ(1, n);
- ASSERT_EQ(2, n);
-}
-
-// Another helper function for testing SCOPED_TRACE.
-void SubWithTrace(int n) {
- SCOPED_TRACE(testing::Message() << "n = " << n);
-
- SubWithoutTrace(n);
-}
-
-TEST(SCOPED_TRACETest, AcceptedValues) {
- SCOPED_TRACE("literal string");
- SCOPED_TRACE(std::string("std::string"));
- SCOPED_TRACE(1337); // streamable type
- const char* null_value = nullptr;
- SCOPED_TRACE(null_value);
-
- ADD_FAILURE() << "Just checking that all these values work fine.";
-}
-
-// Tests that SCOPED_TRACE() obeys lexical scopes.
-TEST(SCOPED_TRACETest, ObeysScopes) {
- printf("(expected to fail)\n");
-
- // There should be no trace before SCOPED_TRACE() is invoked.
- ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
-
- {
- SCOPED_TRACE("Expected trace");
- // After SCOPED_TRACE(), a failure in the current scope should contain
- // the trace.
- ADD_FAILURE() << "This failure is expected, and should have a trace.";
- }
-
- // Once the control leaves the scope of the SCOPED_TRACE(), there
- // should be no trace again.
- ADD_FAILURE() << "This failure is expected, and shouldn't have a trace.";
-}
-
-// Tests that SCOPED_TRACE works inside a loop.
-TEST(SCOPED_TRACETest, WorksInLoop) {
- printf("(expected to fail)\n");
-
- for (int i = 1; i <= 2; i++) {
- SCOPED_TRACE(testing::Message() << "i = " << i);
-
- SubWithoutTrace(i);
- }
-}
-
-// Tests that SCOPED_TRACE works in a subroutine.
-TEST(SCOPED_TRACETest, WorksInSubroutine) {
- printf("(expected to fail)\n");
-
- SubWithTrace(1);
- SubWithTrace(2);
-}
-
-// Tests that SCOPED_TRACE can be nested.
-TEST(SCOPED_TRACETest, CanBeNested) {
- printf("(expected to fail)\n");
-
- SCOPED_TRACE(""); // A trace without a message.
-
- SubWithTrace(2);
-}
-
-// Tests that multiple SCOPED_TRACEs can be used in the same scope.
-TEST(SCOPED_TRACETest, CanBeRepeated) {
- printf("(expected to fail)\n");
-
- SCOPED_TRACE("A");
- ADD_FAILURE()
- << "This failure is expected, and should contain trace point A.";
-
- SCOPED_TRACE("B");
- ADD_FAILURE()
- << "This failure is expected, and should contain trace point A and B.";
-
- {
- SCOPED_TRACE("C");
- ADD_FAILURE() << "This failure is expected, and should "
- << "contain trace point A, B, and C.";
- }
-
- SCOPED_TRACE("D");
- ADD_FAILURE() << "This failure is expected, and should "
- << "contain trace point A, B, and D.";
-}
-
-#if GTEST_IS_THREADSAFE
-// Tests that SCOPED_TRACE()s can be used concurrently from multiple
-// threads. Namely, an assertion should be affected by
-// SCOPED_TRACE()s in its own thread only.
-
-// Here's the sequence of actions that happen in the test:
-//
-// Thread A (main) | Thread B (spawned)
-// ===============================|================================
-// spawns thread B |
-// -------------------------------+--------------------------------
-// waits for n1 | SCOPED_TRACE("Trace B");
-// | generates failure #1
-// | notifies n1
-// -------------------------------+--------------------------------
-// SCOPED_TRACE("Trace A"); | waits for n2
-// generates failure #2 |
-// notifies n2 |
-// -------------------------------|--------------------------------
-// waits for n3 | generates failure #3
-// | trace B dies
-// | generates failure #4
-// | notifies n3
-// -------------------------------|--------------------------------
-// generates failure #5 | finishes
-// trace A dies |
-// generates failure #6 |
-// -------------------------------|--------------------------------
-// waits for thread B to finish |
-
-struct CheckPoints {
- Notification n1;
- Notification n2;
- Notification n3;
-};
-
-static void ThreadWithScopedTrace(CheckPoints* check_points) {
- {
- SCOPED_TRACE("Trace B");
- ADD_FAILURE()
- << "Expected failure #1 (in thread B, only trace B alive).";
- check_points->n1.Notify();
- check_points->n2.WaitForNotification();
-
- ADD_FAILURE()
- << "Expected failure #3 (in thread B, trace A & B both alive).";
- } // Trace B dies here.
- ADD_FAILURE()
- << "Expected failure #4 (in thread B, only trace A alive).";
- check_points->n3.Notify();
-}
-
-TEST(SCOPED_TRACETest, WorksConcurrently) {
- printf("(expecting 6 failures)\n");
-
- CheckPoints check_points;
- ThreadWithParam<CheckPoints*> thread(&ThreadWithScopedTrace, &check_points,
- nullptr);
- check_points.n1.WaitForNotification();
-
- {
- SCOPED_TRACE("Trace A");
- ADD_FAILURE()
- << "Expected failure #2 (in thread A, trace A & B both alive).";
- check_points.n2.Notify();
- check_points.n3.WaitForNotification();
-
- ADD_FAILURE()
- << "Expected failure #5 (in thread A, only trace A alive).";
- } // Trace A dies here.
- ADD_FAILURE()
- << "Expected failure #6 (in thread A, no trace alive).";
- thread.Join();
-}
-#endif // GTEST_IS_THREADSAFE
-
-// Tests basic functionality of the ScopedTrace utility (most of its features
-// are already tested in SCOPED_TRACETest).
-TEST(ScopedTraceTest, WithExplicitFileAndLine) {
- testing::ScopedTrace trace("explicit_file.cc", 123, "expected trace message");
- ADD_FAILURE() << "Check that the trace is attached to a particular location.";
-}
-
-TEST(DisabledTestsWarningTest,
- DISABLED_AlsoRunDisabledTestsFlagSuppressesWarning) {
- // This test body is intentionally empty. Its sole purpose is for
- // verifying that the --gtest_also_run_disabled_tests flag
- // suppresses the "YOU HAVE 12 DISABLED TESTS" warning at the end of
- // the test output.
-}
-
-// Tests using assertions outside of TEST and TEST_F.
-//
-// This function creates two failures intentionally.
-void AdHocTest() {
- printf("The non-test part of the code is expected to have 2 failures.\n\n");
- EXPECT_TRUE(false);
- EXPECT_EQ(2, 3);
-}
-
-// Runs all TESTs, all TEST_Fs, and the ad hoc test.
-int RunAllTests() {
- AdHocTest();
- return RUN_ALL_TESTS();
-}
-
-// Tests non-fatal failures in the fixture constructor.
-class NonFatalFailureInFixtureConstructorTest : public testing::Test {
- protected:
- NonFatalFailureInFixtureConstructorTest() {
- printf("(expecting 5 failures)\n");
- ADD_FAILURE() << "Expected failure #1, in the test fixture c'tor.";
- }
-
- ~NonFatalFailureInFixtureConstructorTest() override {
- ADD_FAILURE() << "Expected failure #5, in the test fixture d'tor.";
- }
-
- void SetUp() override { ADD_FAILURE() << "Expected failure #2, in SetUp()."; }
-
- void TearDown() override {
- ADD_FAILURE() << "Expected failure #4, in TearDown.";
- }
-};
-
-TEST_F(NonFatalFailureInFixtureConstructorTest, FailureInConstructor) {
- ADD_FAILURE() << "Expected failure #3, in the test body.";
-}
-
-// Tests fatal failures in the fixture constructor.
-class FatalFailureInFixtureConstructorTest : public testing::Test {
- protected:
- FatalFailureInFixtureConstructorTest() {
- printf("(expecting 2 failures)\n");
- Init();
- }
-
- ~FatalFailureInFixtureConstructorTest() override {
- ADD_FAILURE() << "Expected failure #2, in the test fixture d'tor.";
- }
-
- void SetUp() override {
- ADD_FAILURE() << "UNEXPECTED failure in SetUp(). "
- << "We should never get here, as the test fixture c'tor "
- << "had a fatal failure.";
- }
-
- void TearDown() override {
- ADD_FAILURE() << "UNEXPECTED failure in TearDown(). "
- << "We should never get here, as the test fixture c'tor "
- << "had a fatal failure.";
- }
-
- private:
- void Init() {
- FAIL() << "Expected failure #1, in the test fixture c'tor.";
- }
-};
-
-TEST_F(FatalFailureInFixtureConstructorTest, FailureInConstructor) {
- ADD_FAILURE() << "UNEXPECTED failure in the test body. "
- << "We should never get here, as the test fixture c'tor "
- << "had a fatal failure.";
-}
-
-// Tests non-fatal failures in SetUp().
-class NonFatalFailureInSetUpTest : public testing::Test {
- protected:
- ~NonFatalFailureInSetUpTest() override { Deinit(); }
-
- void SetUp() override {
- printf("(expecting 4 failures)\n");
- ADD_FAILURE() << "Expected failure #1, in SetUp().";
- }
-
- void TearDown() override { FAIL() << "Expected failure #3, in TearDown()."; }
-
- private:
- void Deinit() {
- FAIL() << "Expected failure #4, in the test fixture d'tor.";
- }
-};
-
-TEST_F(NonFatalFailureInSetUpTest, FailureInSetUp) {
- FAIL() << "Expected failure #2, in the test function.";
-}
-
-// Tests fatal failures in SetUp().
-class FatalFailureInSetUpTest : public testing::Test {
- protected:
- ~FatalFailureInSetUpTest() override { Deinit(); }
-
- void SetUp() override {
- printf("(expecting 3 failures)\n");
- FAIL() << "Expected failure #1, in SetUp().";
- }
-
- void TearDown() override { FAIL() << "Expected failure #2, in TearDown()."; }
-
- private:
- void Deinit() {
- FAIL() << "Expected failure #3, in the test fixture d'tor.";
- }
-};
-
-TEST_F(FatalFailureInSetUpTest, FailureInSetUp) {
- FAIL() << "UNEXPECTED failure in the test function. "
- << "We should never get here, as SetUp() failed.";
-}
-
-TEST(AddFailureAtTest, MessageContainsSpecifiedFileAndLineNumber) {
- ADD_FAILURE_AT("foo.cc", 42) << "Expected nonfatal failure in foo.cc";
-}
-
-TEST(GtestFailAtTest, MessageContainsSpecifiedFileAndLineNumber) {
- GTEST_FAIL_AT("foo.cc", 42) << "Expected fatal failure in foo.cc";
-}
-
-#if GTEST_IS_THREADSAFE
-
-// A unary function that may die.
-void DieIf(bool should_die) {
- GTEST_CHECK_(!should_die) << " - death inside DieIf().";
-}
-
-// Tests running death tests in a multi-threaded context.
-
-// Used for coordination between the main and the spawn thread.
-struct SpawnThreadNotifications {
- SpawnThreadNotifications() {}
-
- Notification spawn_thread_started;
- Notification spawn_thread_ok_to_terminate;
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(SpawnThreadNotifications);
-};
-
-// The function to be executed in the thread spawn by the
-// MultipleThreads test (below).
-static void ThreadRoutine(SpawnThreadNotifications* notifications) {
- // Signals the main thread that this thread has started.
- notifications->spawn_thread_started.Notify();
-
- // Waits for permission to finish from the main thread.
- notifications->spawn_thread_ok_to_terminate.WaitForNotification();
-}
-
-// This is a death-test test, but it's not named with a DeathTest
-// suffix. It starts threads which might interfere with later
-// death tests, so it must run after all other death tests.
-class DeathTestAndMultiThreadsTest : public testing::Test {
- protected:
- // Starts a thread and waits for it to begin.
- void SetUp() override {
- thread_.reset(new ThreadWithParam<SpawnThreadNotifications*>(
- &ThreadRoutine, ¬ifications_, nullptr));
- notifications_.spawn_thread_started.WaitForNotification();
- }
- // Tells the thread to finish, and reaps it.
- // Depending on the version of the thread library in use,
- // a manager thread might still be left running that will interfere
- // with later death tests. This is unfortunate, but this class
- // cleans up after itself as best it can.
- void TearDown() override {
- notifications_.spawn_thread_ok_to_terminate.Notify();
- }
-
- private:
- SpawnThreadNotifications notifications_;
- std::unique_ptr<ThreadWithParam<SpawnThreadNotifications*> > thread_;
-};
-
-#endif // GTEST_IS_THREADSAFE
-
-// The MixedUpTestSuiteTest test case verifies that Google Test will fail a
-// test if it uses a different fixture class than what other tests in
-// the same test case use. It deliberately contains two fixture
-// classes with the same name but defined in different namespaces.
-
-// The MixedUpTestSuiteWithSameTestNameTest test case verifies that
-// when the user defines two tests with the same test case name AND
-// same test name (but in different namespaces), the second test will
-// fail.
-
-namespace foo {
-
-class MixedUpTestSuiteTest : public testing::Test {
-};
-
-TEST_F(MixedUpTestSuiteTest, FirstTestFromNamespaceFoo) {}
-TEST_F(MixedUpTestSuiteTest, SecondTestFromNamespaceFoo) {}
-
-class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {
-};
-
-TEST_F(MixedUpTestSuiteWithSameTestNameTest,
- TheSecondTestWithThisNameShouldFail) {}
-
-} // namespace foo
-
-namespace bar {
-
-class MixedUpTestSuiteTest : public testing::Test {
-};
-
-// The following two tests are expected to fail. We rely on the
-// golden file to check that Google Test generates the right error message.
-TEST_F(MixedUpTestSuiteTest, ThisShouldFail) {}
-TEST_F(MixedUpTestSuiteTest, ThisShouldFailToo) {}
-
-class MixedUpTestSuiteWithSameTestNameTest : public testing::Test {
-};
-
-// Expected to fail. We rely on the golden file to check that Google Test
-// generates the right error message.
-TEST_F(MixedUpTestSuiteWithSameTestNameTest,
- TheSecondTestWithThisNameShouldFail) {}
-
-} // namespace bar
-
-// The following two test cases verify that Google Test catches the user
-// error of mixing TEST and TEST_F in the same test case. The first
-// test case checks the scenario where TEST_F appears before TEST, and
-// the second one checks where TEST appears before TEST_F.
-
-class TEST_F_before_TEST_in_same_test_case : public testing::Test {
-};
-
-TEST_F(TEST_F_before_TEST_in_same_test_case, DefinedUsingTEST_F) {}
-
-// Expected to fail. We rely on the golden file to check that Google Test
-// generates the right error message.
-TEST(TEST_F_before_TEST_in_same_test_case, DefinedUsingTESTAndShouldFail) {}
-
-class TEST_before_TEST_F_in_same_test_case : public testing::Test {
-};
-
-TEST(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST) {}
-
-// Expected to fail. We rely on the golden file to check that Google Test
-// generates the right error message.
-TEST_F(TEST_before_TEST_F_in_same_test_case, DefinedUsingTEST_FAndShouldFail) {
-}
-
-// Used for testing EXPECT_NONFATAL_FAILURE() and EXPECT_FATAL_FAILURE().
-int global_integer = 0;
-
-// Tests that EXPECT_NONFATAL_FAILURE() can reference global variables.
-TEST(ExpectNonfatalFailureTest, CanReferenceGlobalVariables) {
- global_integer = 0;
- EXPECT_NONFATAL_FAILURE({
- EXPECT_EQ(1, global_integer) << "Expected non-fatal failure.";
- }, "Expected non-fatal failure.");
-}
-
-// Tests that EXPECT_NONFATAL_FAILURE() can reference local variables
-// (static or not).
-TEST(ExpectNonfatalFailureTest, CanReferenceLocalVariables) {
- int m = 0;
- static int n;
- n = 1;
- EXPECT_NONFATAL_FAILURE({
- EXPECT_EQ(m, n) << "Expected non-fatal failure.";
- }, "Expected non-fatal failure.");
-}
-
-// Tests that EXPECT_NONFATAL_FAILURE() succeeds when there is exactly
-// one non-fatal failure and no fatal failure.
-TEST(ExpectNonfatalFailureTest, SucceedsWhenThereIsOneNonfatalFailure) {
- EXPECT_NONFATAL_FAILURE({
- ADD_FAILURE() << "Expected non-fatal failure.";
- }, "Expected non-fatal failure.");
-}
-
-// Tests that EXPECT_NONFATAL_FAILURE() fails when there is no
-// non-fatal failure.
-TEST(ExpectNonfatalFailureTest, FailsWhenThereIsNoNonfatalFailure) {
- printf("(expecting a failure)\n");
- EXPECT_NONFATAL_FAILURE({
- }, "");
-}
-
-// Tests that EXPECT_NONFATAL_FAILURE() fails when there are two
-// non-fatal failures.
-TEST(ExpectNonfatalFailureTest, FailsWhenThereAreTwoNonfatalFailures) {
- printf("(expecting a failure)\n");
- EXPECT_NONFATAL_FAILURE({
- ADD_FAILURE() << "Expected non-fatal failure 1.";
- ADD_FAILURE() << "Expected non-fatal failure 2.";
- }, "");
-}
-
-// Tests that EXPECT_NONFATAL_FAILURE() fails when there is one fatal
-// failure.
-TEST(ExpectNonfatalFailureTest, FailsWhenThereIsOneFatalFailure) {
- printf("(expecting a failure)\n");
- EXPECT_NONFATAL_FAILURE({
- FAIL() << "Expected fatal failure.";
- }, "");
-}
-
-// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
-// tested returns.
-TEST(ExpectNonfatalFailureTest, FailsWhenStatementReturns) {
- printf("(expecting a failure)\n");
- EXPECT_NONFATAL_FAILURE({
- return;
- }, "");
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-// Tests that EXPECT_NONFATAL_FAILURE() fails when the statement being
-// tested throws.
-TEST(ExpectNonfatalFailureTest, FailsWhenStatementThrows) {
- printf("(expecting a failure)\n");
- try {
- EXPECT_NONFATAL_FAILURE({
- throw 0;
- }, "");
- } catch(int) { // NOLINT
- }
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// Tests that EXPECT_FATAL_FAILURE() can reference global variables.
-TEST(ExpectFatalFailureTest, CanReferenceGlobalVariables) {
- global_integer = 0;
- EXPECT_FATAL_FAILURE({
- ASSERT_EQ(1, global_integer) << "Expected fatal failure.";
- }, "Expected fatal failure.");
-}
-
-// Tests that EXPECT_FATAL_FAILURE() can reference local static
-// variables.
-TEST(ExpectFatalFailureTest, CanReferenceLocalStaticVariables) {
- static int n;
- n = 1;
- EXPECT_FATAL_FAILURE({
- ASSERT_EQ(0, n) << "Expected fatal failure.";
- }, "Expected fatal failure.");
-}
-
-// Tests that EXPECT_FATAL_FAILURE() succeeds when there is exactly
-// one fatal failure and no non-fatal failure.
-TEST(ExpectFatalFailureTest, SucceedsWhenThereIsOneFatalFailure) {
- EXPECT_FATAL_FAILURE({
- FAIL() << "Expected fatal failure.";
- }, "Expected fatal failure.");
-}
-
-// Tests that EXPECT_FATAL_FAILURE() fails when there is no fatal
-// failure.
-TEST(ExpectFatalFailureTest, FailsWhenThereIsNoFatalFailure) {
- printf("(expecting a failure)\n");
- EXPECT_FATAL_FAILURE({
- }, "");
-}
-
-// A helper for generating a fatal failure.
-void FatalFailure() {
- FAIL() << "Expected fatal failure.";
-}
-
-// Tests that EXPECT_FATAL_FAILURE() fails when there are two
-// fatal failures.
-TEST(ExpectFatalFailureTest, FailsWhenThereAreTwoFatalFailures) {
- printf("(expecting a failure)\n");
- EXPECT_FATAL_FAILURE({
- FatalFailure();
- FatalFailure();
- }, "");
-}
-
-// Tests that EXPECT_FATAL_FAILURE() fails when there is one non-fatal
-// failure.
-TEST(ExpectFatalFailureTest, FailsWhenThereIsOneNonfatalFailure) {
- printf("(expecting a failure)\n");
- EXPECT_FATAL_FAILURE({
- ADD_FAILURE() << "Expected non-fatal failure.";
- }, "");
-}
-
-// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
-// tested returns.
-TEST(ExpectFatalFailureTest, FailsWhenStatementReturns) {
- printf("(expecting a failure)\n");
- EXPECT_FATAL_FAILURE({
- return;
- }, "");
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-// Tests that EXPECT_FATAL_FAILURE() fails when the statement being
-// tested throws.
-TEST(ExpectFatalFailureTest, FailsWhenStatementThrows) {
- printf("(expecting a failure)\n");
- try {
- EXPECT_FATAL_FAILURE({
- throw 0;
- }, "");
- } catch(int) { // NOLINT
- }
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// This #ifdef block tests the output of value-parameterized tests.
-
-std::string ParamNameFunc(const testing::TestParamInfo<std::string>& info) {
- return info.param;
-}
-
-class ParamTest : public testing::TestWithParam<std::string> {
-};
-
-TEST_P(ParamTest, Success) {
- EXPECT_EQ("a", GetParam());
-}
-
-TEST_P(ParamTest, Failure) {
- EXPECT_EQ("b", GetParam()) << "Expected failure";
-}
-
-INSTANTIATE_TEST_SUITE_P(PrintingStrings,
- ParamTest,
- testing::Values(std::string("a")),
- ParamNameFunc);
-
-// This #ifdef block tests the output of typed tests.
-#if GTEST_HAS_TYPED_TEST
-
-template <typename T>
-class TypedTest : public testing::Test {
-};
-
-TYPED_TEST_SUITE(TypedTest, testing::Types<int>);
-
-TYPED_TEST(TypedTest, Success) {
- EXPECT_EQ(0, TypeParam());
-}
-
-TYPED_TEST(TypedTest, Failure) {
- EXPECT_EQ(1, TypeParam()) << "Expected failure";
-}
-
-typedef testing::Types<char, int> TypesForTestWithNames;
-
-template <typename T>
-class TypedTestWithNames : public testing::Test {};
-
-class TypedTestNames {
- public:
- template <typename T>
- static std::string GetName(int i) {
- if (std::is_same<T, char>::value)
- return std::string("char") + ::testing::PrintToString(i);
- if (std::is_same<T, int>::value)
- return std::string("int") + ::testing::PrintToString(i);
- }
-};
-
-TYPED_TEST_SUITE(TypedTestWithNames, TypesForTestWithNames, TypedTestNames);
-
-TYPED_TEST(TypedTestWithNames, Success) {}
-
-TYPED_TEST(TypedTestWithNames, Failure) { FAIL(); }
-
-#endif // GTEST_HAS_TYPED_TEST
-
-// This #ifdef block tests the output of type-parameterized tests.
-#if GTEST_HAS_TYPED_TEST_P
-
-template <typename T>
-class TypedTestP : public testing::Test {
-};
-
-TYPED_TEST_SUITE_P(TypedTestP);
-
-TYPED_TEST_P(TypedTestP, Success) {
- EXPECT_EQ(0U, TypeParam());
-}
-
-TYPED_TEST_P(TypedTestP, Failure) {
- EXPECT_EQ(1U, TypeParam()) << "Expected failure";
-}
-
-REGISTER_TYPED_TEST_SUITE_P(TypedTestP, Success, Failure);
-
-typedef testing::Types<unsigned char, unsigned int> UnsignedTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(Unsigned, TypedTestP, UnsignedTypes);
-
-class TypedTestPNames {
- public:
- template <typename T>
- static std::string GetName(int i) {
- if (std::is_same<T, unsigned char>::value) {
- return std::string("unsignedChar") + ::testing::PrintToString(i);
- }
- if (std::is_same<T, unsigned int>::value) {
- return std::string("unsignedInt") + ::testing::PrintToString(i);
- }
- }
-};
-
-INSTANTIATE_TYPED_TEST_SUITE_P(UnsignedCustomName, TypedTestP, UnsignedTypes,
- TypedTestPNames);
-
-#endif // GTEST_HAS_TYPED_TEST_P
-
-#if GTEST_HAS_DEATH_TEST
-
-// We rely on the golden file to verify that tests whose test case
-// name ends with DeathTest are run first.
-
-TEST(ADeathTest, ShouldRunFirst) {
-}
-
-# if GTEST_HAS_TYPED_TEST
-
-// We rely on the golden file to verify that typed tests whose test
-// case name ends with DeathTest are run first.
-
-template <typename T>
-class ATypedDeathTest : public testing::Test {
-};
-
-typedef testing::Types<int, double> NumericTypes;
-TYPED_TEST_SUITE(ATypedDeathTest, NumericTypes);
-
-TYPED_TEST(ATypedDeathTest, ShouldRunFirst) {
-}
-
-# endif // GTEST_HAS_TYPED_TEST
-
-# if GTEST_HAS_TYPED_TEST_P
-
-
-// We rely on the golden file to verify that type-parameterized tests
-// whose test case name ends with DeathTest are run first.
-
-template <typename T>
-class ATypeParamDeathTest : public testing::Test {
-};
-
-TYPED_TEST_SUITE_P(ATypeParamDeathTest);
-
-TYPED_TEST_P(ATypeParamDeathTest, ShouldRunFirst) {
-}
-
-REGISTER_TYPED_TEST_SUITE_P(ATypeParamDeathTest, ShouldRunFirst);
-
-INSTANTIATE_TYPED_TEST_SUITE_P(My, ATypeParamDeathTest, NumericTypes);
-
-# endif // GTEST_HAS_TYPED_TEST_P
-
-#endif // GTEST_HAS_DEATH_TEST
-
-// Tests various failure conditions of
-// EXPECT_{,NON}FATAL_FAILURE{,_ON_ALL_THREADS}.
-class ExpectFailureTest : public testing::Test {
- public: // Must be public and not protected due to a bug in g++ 3.4.2.
- enum FailureMode {
- FATAL_FAILURE,
- NONFATAL_FAILURE
- };
- static void AddFailure(FailureMode failure) {
- if (failure == FATAL_FAILURE) {
- FAIL() << "Expected fatal failure.";
- } else {
- ADD_FAILURE() << "Expected non-fatal failure.";
- }
- }
-};
-
-TEST_F(ExpectFailureTest, ExpectFatalFailure) {
- // Expected fatal failure, but succeeds.
- printf("(expecting 1 failure)\n");
- EXPECT_FATAL_FAILURE(SUCCEED(), "Expected fatal failure.");
- // Expected fatal failure, but got a non-fatal failure.
- printf("(expecting 1 failure)\n");
- EXPECT_FATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Expected non-fatal "
- "failure.");
- // Wrong message.
- printf("(expecting 1 failure)\n");
- EXPECT_FATAL_FAILURE(AddFailure(FATAL_FAILURE), "Some other fatal failure "
- "expected.");
-}
-
-TEST_F(ExpectFailureTest, ExpectNonFatalFailure) {
- // Expected non-fatal failure, but succeeds.
- printf("(expecting 1 failure)\n");
- EXPECT_NONFATAL_FAILURE(SUCCEED(), "Expected non-fatal failure.");
- // Expected non-fatal failure, but got a fatal failure.
- printf("(expecting 1 failure)\n");
- EXPECT_NONFATAL_FAILURE(AddFailure(FATAL_FAILURE), "Expected fatal failure.");
- // Wrong message.
- printf("(expecting 1 failure)\n");
- EXPECT_NONFATAL_FAILURE(AddFailure(NONFATAL_FAILURE), "Some other non-fatal "
- "failure.");
-}
-
-#if GTEST_IS_THREADSAFE
-
-class ExpectFailureWithThreadsTest : public ExpectFailureTest {
- protected:
- static void AddFailureInOtherThread(FailureMode failure) {
- ThreadWithParam<FailureMode> thread(&AddFailure, failure, nullptr);
- thread.Join();
- }
-};
-
-TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailure) {
- // We only intercept the current thread.
- printf("(expecting 2 failures)\n");
- EXPECT_FATAL_FAILURE(AddFailureInOtherThread(FATAL_FAILURE),
- "Expected fatal failure.");
-}
-
-TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailure) {
- // We only intercept the current thread.
- printf("(expecting 2 failures)\n");
- EXPECT_NONFATAL_FAILURE(AddFailureInOtherThread(NONFATAL_FAILURE),
- "Expected non-fatal failure.");
-}
-
-typedef ExpectFailureWithThreadsTest ScopedFakeTestPartResultReporterTest;
-
-// Tests that the ScopedFakeTestPartResultReporter only catches failures from
-// the current thread if it is instantiated with INTERCEPT_ONLY_CURRENT_THREAD.
-TEST_F(ScopedFakeTestPartResultReporterTest, InterceptOnlyCurrentThread) {
- printf("(expecting 2 failures)\n");
- TestPartResultArray results;
- {
- ScopedFakeTestPartResultReporter reporter(
- ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
- &results);
- AddFailureInOtherThread(FATAL_FAILURE);
- AddFailureInOtherThread(NONFATAL_FAILURE);
- }
- // The two failures should not have been intercepted.
- EXPECT_EQ(0, results.size()) << "This shouldn't fail.";
-}
-
-#endif // GTEST_IS_THREADSAFE
-
-TEST_F(ExpectFailureTest, ExpectFatalFailureOnAllThreads) {
- // Expected fatal failure, but succeeds.
- printf("(expecting 1 failure)\n");
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected fatal failure.");
- // Expected fatal failure, but got a non-fatal failure.
- printf("(expecting 1 failure)\n");
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
- "Expected non-fatal failure.");
- // Wrong message.
- printf("(expecting 1 failure)\n");
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
- "Some other fatal failure expected.");
-}
-
-TEST_F(ExpectFailureTest, ExpectNonFatalFailureOnAllThreads) {
- // Expected non-fatal failure, but succeeds.
- printf("(expecting 1 failure)\n");
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(SUCCEED(), "Expected non-fatal "
- "failure.");
- // Expected non-fatal failure, but got a fatal failure.
- printf("(expecting 1 failure)\n");
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(FATAL_FAILURE),
- "Expected fatal failure.");
- // Wrong message.
- printf("(expecting 1 failure)\n");
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddFailure(NONFATAL_FAILURE),
- "Some other non-fatal failure.");
-}
-
-class DynamicFixture : public testing::Test {
- protected:
- DynamicFixture() { printf("DynamicFixture()\n"); }
- ~DynamicFixture() override { printf("~DynamicFixture()\n"); }
- void SetUp() override { printf("DynamicFixture::SetUp\n"); }
- void TearDown() override { printf("DynamicFixture::TearDown\n"); }
-
- static void SetUpTestSuite() { printf("DynamicFixture::SetUpTestSuite\n"); }
- static void TearDownTestSuite() {
- printf("DynamicFixture::TearDownTestSuite\n");
- }
-};
-
-template <bool Pass>
-class DynamicTest : public DynamicFixture {
- public:
- void TestBody() override { EXPECT_TRUE(Pass); }
-};
-
-auto dynamic_test = (
- // Register two tests with the same fixture correctly.
- testing::RegisterTest(
- "DynamicFixture", "DynamicTestPass", nullptr, nullptr, __FILE__,
- __LINE__, []() -> DynamicFixture* { return new DynamicTest<true>; }),
- testing::RegisterTest(
- "DynamicFixture", "DynamicTestFail", nullptr, nullptr, __FILE__,
- __LINE__, []() -> DynamicFixture* { return new DynamicTest<false>; }),
-
- // Register the same fixture with another name. That's fine.
- testing::RegisterTest(
- "DynamicFixtureAnotherName", "DynamicTestPass", nullptr, nullptr,
- __FILE__, __LINE__,
- []() -> DynamicFixture* { return new DynamicTest<true>; }),
-
- // Register two tests with the same fixture incorrectly.
- testing::RegisterTest(
- "BadDynamicFixture1", "FixtureBase", nullptr, nullptr, __FILE__,
- __LINE__, []() -> DynamicFixture* { return new DynamicTest<true>; }),
- testing::RegisterTest(
- "BadDynamicFixture1", "TestBase", nullptr, nullptr, __FILE__, __LINE__,
- []() -> testing::Test* { return new DynamicTest<true>; }),
-
- // Register two tests with the same fixture incorrectly by ommiting the
- // return type.
- testing::RegisterTest(
- "BadDynamicFixture2", "FixtureBase", nullptr, nullptr, __FILE__,
- __LINE__, []() -> DynamicFixture* { return new DynamicTest<true>; }),
- testing::RegisterTest("BadDynamicFixture2", "Derived", nullptr, nullptr,
- __FILE__, __LINE__,
- []() { return new DynamicTest<true>; }));
-
-// Two test environments for testing testing::AddGlobalTestEnvironment().
-
-class FooEnvironment : public testing::Environment {
- public:
- void SetUp() override { printf("%s", "FooEnvironment::SetUp() called.\n"); }
-
- void TearDown() override {
- printf("%s", "FooEnvironment::TearDown() called.\n");
- FAIL() << "Expected fatal failure.";
- }
-};
-
-class BarEnvironment : public testing::Environment {
- public:
- void SetUp() override { printf("%s", "BarEnvironment::SetUp() called.\n"); }
-
- void TearDown() override {
- printf("%s", "BarEnvironment::TearDown() called.\n");
- ADD_FAILURE() << "Expected non-fatal failure.";
- }
-};
-
-// The main function.
-//
-// The idea is to use Google Test to run all the tests we have defined (some
-// of them are intended to fail), and then compare the test results
-// with the "golden" file.
-int main(int argc, char **argv) {
- testing::GTEST_FLAG(print_time) = false;
-
- // We just run the tests, knowing some of them are intended to fail.
- // We will use a separate Python script to compare the output of
- // this program with the golden file.
-
- // It's hard to test InitGoogleTest() directly, as it has many
- // global side effects. The following line serves as a sanity test
- // for it.
- testing::InitGoogleTest(&argc, argv);
- bool internal_skip_environment_and_ad_hoc_tests =
- std::count(argv, argv + argc,
- std::string("internal_skip_environment_and_ad_hoc_tests")) > 0;
-
-#if GTEST_HAS_DEATH_TEST
- if (testing::internal::GTEST_FLAG(internal_run_death_test) != "") {
- // Skip the usual output capturing if we're running as the child
- // process of an threadsafe-style death test.
-# if GTEST_OS_WINDOWS
- posix::FReopen("nul:", "w", stdout);
-# else
- posix::FReopen("/dev/null", "w", stdout);
-# endif // GTEST_OS_WINDOWS
- return RUN_ALL_TESTS();
- }
-#endif // GTEST_HAS_DEATH_TEST
-
- if (internal_skip_environment_and_ad_hoc_tests)
- return RUN_ALL_TESTS();
-
- // Registers two global test environments.
- // The golden file verifies that they are set up in the order they
- // are registered, and torn down in the reverse order.
- testing::AddGlobalTestEnvironment(new FooEnvironment);
- testing::AddGlobalTestEnvironment(new BarEnvironment);
-#if _MSC_VER
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4127
-#endif // _MSC_VER
- return RunAllTests();
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2015 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Verifies that Google Test warns the user when not initialized properly."""
-
-import gtest_test_utils
-
-binary_name = 'googletest-param-test-invalid-name1-test_'
-COMMAND = gtest_test_utils.GetTestExecutablePath(binary_name)
-
-
-def Assert(condition):
- if not condition:
- raise AssertionError
-
-
-def TestExitCodeAndOutput(command):
- """Runs the given command and verifies its exit code and output."""
-
- err = ('Parameterized test name \'"InvalidWithQuotes"\' is invalid')
-
- p = gtest_test_utils.Subprocess(command)
- Assert(p.terminated_by_signal)
-
- # Verify the output message contains appropriate output
- Assert(err in p.output)
-
-
-class GTestParamTestInvalidName1Test(gtest_test_utils.TestCase):
-
- def testExitCodeAndOutput(self):
- TestExitCodeAndOutput(COMMAND)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "gtest/gtest.h"
-
-namespace {
-class DummyTest : public ::testing::TestWithParam<const char *> {};
-
-TEST_P(DummyTest, Dummy) {
-}
-
-INSTANTIATE_TEST_SUITE_P(InvalidTestName,
- DummyTest,
- ::testing::Values("InvalidWithQuotes"),
- ::testing::PrintToStringParamName());
-
-} // namespace
-
-int main(int argc, char *argv[]) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2015 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Verifies that Google Test warns the user when not initialized properly."""
-
-import gtest_test_utils
-
-binary_name = 'googletest-param-test-invalid-name2-test_'
-COMMAND = gtest_test_utils.GetTestExecutablePath(binary_name)
-
-
-def Assert(condition):
- if not condition:
- raise AssertionError
-
-
-def TestExitCodeAndOutput(command):
- """Runs the given command and verifies its exit code and output."""
-
- err = ('Duplicate parameterized test name \'a\'')
-
- p = gtest_test_utils.Subprocess(command)
- Assert(p.terminated_by_signal)
-
- # Check for appropriate output
- Assert(err in p.output)
-
-
-class GTestParamTestInvalidName2Test(gtest_test_utils.TestCase):
-
- def testExitCodeAndOutput(self):
- TestExitCodeAndOutput(COMMAND)
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "gtest/gtest.h"
-
-namespace {
-class DummyTest : public ::testing::TestWithParam<const char *> {};
-
-std::string StringParamTestSuffix(
- const testing::TestParamInfo<const char*>& info) {
- return std::string(info.param);
-}
-
-TEST_P(DummyTest, Dummy) {
-}
-
-INSTANTIATE_TEST_SUITE_P(DuplicateTestNames,
- DummyTest,
- ::testing::Values("a", "b", "a", "c"),
- StringParamTestSuffix);
-} // namespace
-
-int main(int argc, char *argv[]) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-
-
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for Google Test itself. This file verifies that the parameter
-// generators objects produce correct parameter sequences and that
-// Google Test runtime instantiates correct tests from those sequences.
-
-#include "gtest/gtest.h"
-
-# include <algorithm>
-# include <iostream>
-# include <list>
-# include <sstream>
-# include <string>
-# include <vector>
-
-# include "src/gtest-internal-inl.h" // for UnitTestOptions
-# include "test/googletest-param-test-test.h"
-
-using ::std::vector;
-using ::std::sort;
-
-using ::testing::AddGlobalTestEnvironment;
-using ::testing::Bool;
-using ::testing::Combine;
-using ::testing::Message;
-using ::testing::Range;
-using ::testing::TestWithParam;
-using ::testing::Values;
-using ::testing::ValuesIn;
-
-using ::testing::internal::ParamGenerator;
-using ::testing::internal::UnitTestOptions;
-
-// Prints a value to a string.
-//
-// FIXME: remove PrintValue() when we move matchers and
-// EXPECT_THAT() from Google Mock to Google Test. At that time, we
-// can write EXPECT_THAT(x, Eq(y)) to compare two tuples x and y, as
-// EXPECT_THAT() and the matchers know how to print tuples.
-template <typename T>
-::std::string PrintValue(const T& value) {
- return testing::PrintToString(value);
-}
-
-// Verifies that a sequence generated by the generator and accessed
-// via the iterator object matches the expected one using Google Test
-// assertions.
-template <typename T, size_t N>
-void VerifyGenerator(const ParamGenerator<T>& generator,
- const T (&expected_values)[N]) {
- typename ParamGenerator<T>::iterator it = generator.begin();
- for (size_t i = 0; i < N; ++i) {
- ASSERT_FALSE(it == generator.end())
- << "At element " << i << " when accessing via an iterator "
- << "created with the copy constructor.\n";
- // We cannot use EXPECT_EQ() here as the values may be tuples,
- // which don't support <<.
- EXPECT_TRUE(expected_values[i] == *it)
- << "where i is " << i
- << ", expected_values[i] is " << PrintValue(expected_values[i])
- << ", *it is " << PrintValue(*it)
- << ", and 'it' is an iterator created with the copy constructor.\n";
- ++it;
- }
- EXPECT_TRUE(it == generator.end())
- << "At the presumed end of sequence when accessing via an iterator "
- << "created with the copy constructor.\n";
-
- // Test the iterator assignment. The following lines verify that
- // the sequence accessed via an iterator initialized via the
- // assignment operator (as opposed to a copy constructor) matches
- // just the same.
- it = generator.begin();
- for (size_t i = 0; i < N; ++i) {
- ASSERT_FALSE(it == generator.end())
- << "At element " << i << " when accessing via an iterator "
- << "created with the assignment operator.\n";
- EXPECT_TRUE(expected_values[i] == *it)
- << "where i is " << i
- << ", expected_values[i] is " << PrintValue(expected_values[i])
- << ", *it is " << PrintValue(*it)
- << ", and 'it' is an iterator created with the copy constructor.\n";
- ++it;
- }
- EXPECT_TRUE(it == generator.end())
- << "At the presumed end of sequence when accessing via an iterator "
- << "created with the assignment operator.\n";
-}
-
-template <typename T>
-void VerifyGeneratorIsEmpty(const ParamGenerator<T>& generator) {
- typename ParamGenerator<T>::iterator it = generator.begin();
- EXPECT_TRUE(it == generator.end());
-
- it = generator.begin();
- EXPECT_TRUE(it == generator.end());
-}
-
-// Generator tests. They test that each of the provided generator functions
-// generates an expected sequence of values. The general test pattern
-// instantiates a generator using one of the generator functions,
-// checks the sequence produced by the generator using its iterator API,
-// and then resets the iterator back to the beginning of the sequence
-// and checks the sequence again.
-
-// Tests that iterators produced by generator functions conform to the
-// ForwardIterator concept.
-TEST(IteratorTest, ParamIteratorConformsToForwardIteratorConcept) {
- const ParamGenerator<int> gen = Range(0, 10);
- ParamGenerator<int>::iterator it = gen.begin();
-
- // Verifies that iterator initialization works as expected.
- ParamGenerator<int>::iterator it2 = it;
- EXPECT_TRUE(*it == *it2) << "Initialized iterators must point to the "
- << "element same as its source points to";
-
- // Verifies that iterator assignment works as expected.
- ++it;
- EXPECT_FALSE(*it == *it2);
- it2 = it;
- EXPECT_TRUE(*it == *it2) << "Assigned iterators must point to the "
- << "element same as its source points to";
-
- // Verifies that prefix operator++() returns *this.
- EXPECT_EQ(&it, &(++it)) << "Result of the prefix operator++ must be "
- << "refer to the original object";
-
- // Verifies that the result of the postfix operator++ points to the value
- // pointed to by the original iterator.
- int original_value = *it; // Have to compute it outside of macro call to be
- // unaffected by the parameter evaluation order.
- EXPECT_EQ(original_value, *(it++));
-
- // Verifies that prefix and postfix operator++() advance an iterator
- // all the same.
- it2 = it;
- ++it;
- ++it2;
- EXPECT_TRUE(*it == *it2);
-}
-
-// Tests that Range() generates the expected sequence.
-TEST(RangeTest, IntRangeWithDefaultStep) {
- const ParamGenerator<int> gen = Range(0, 3);
- const int expected_values[] = {0, 1, 2};
- VerifyGenerator(gen, expected_values);
-}
-
-// Edge case. Tests that Range() generates the single element sequence
-// as expected when provided with range limits that are equal.
-TEST(RangeTest, IntRangeSingleValue) {
- const ParamGenerator<int> gen = Range(0, 1);
- const int expected_values[] = {0};
- VerifyGenerator(gen, expected_values);
-}
-
-// Edge case. Tests that Range() with generates empty sequence when
-// supplied with an empty range.
-TEST(RangeTest, IntRangeEmpty) {
- const ParamGenerator<int> gen = Range(0, 0);
- VerifyGeneratorIsEmpty(gen);
-}
-
-// Tests that Range() with custom step (greater then one) generates
-// the expected sequence.
-TEST(RangeTest, IntRangeWithCustomStep) {
- const ParamGenerator<int> gen = Range(0, 9, 3);
- const int expected_values[] = {0, 3, 6};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that Range() with custom step (greater then one) generates
-// the expected sequence when the last element does not fall on the
-// upper range limit. Sequences generated by Range() must not have
-// elements beyond the range limits.
-TEST(RangeTest, IntRangeWithCustomStepOverUpperBound) {
- const ParamGenerator<int> gen = Range(0, 4, 3);
- const int expected_values[] = {0, 3};
- VerifyGenerator(gen, expected_values);
-}
-
-// Verifies that Range works with user-defined types that define
-// copy constructor, operator=(), operator+(), and operator<().
-class DogAdder {
- public:
- explicit DogAdder(const char* a_value) : value_(a_value) {}
- DogAdder(const DogAdder& other) : value_(other.value_.c_str()) {}
-
- DogAdder operator=(const DogAdder& other) {
- if (this != &other)
- value_ = other.value_;
- return *this;
- }
- DogAdder operator+(const DogAdder& other) const {
- Message msg;
- msg << value_.c_str() << other.value_.c_str();
- return DogAdder(msg.GetString().c_str());
- }
- bool operator<(const DogAdder& other) const {
- return value_ < other.value_;
- }
- const std::string& value() const { return value_; }
-
- private:
- std::string value_;
-};
-
-TEST(RangeTest, WorksWithACustomType) {
- const ParamGenerator<DogAdder> gen =
- Range(DogAdder("cat"), DogAdder("catdogdog"), DogAdder("dog"));
- ParamGenerator<DogAdder>::iterator it = gen.begin();
-
- ASSERT_FALSE(it == gen.end());
- EXPECT_STREQ("cat", it->value().c_str());
-
- ASSERT_FALSE(++it == gen.end());
- EXPECT_STREQ("catdog", it->value().c_str());
-
- EXPECT_TRUE(++it == gen.end());
-}
-
-class IntWrapper {
- public:
- explicit IntWrapper(int a_value) : value_(a_value) {}
- IntWrapper(const IntWrapper& other) : value_(other.value_) {}
-
- IntWrapper operator=(const IntWrapper& other) {
- value_ = other.value_;
- return *this;
- }
- // operator+() adds a different type.
- IntWrapper operator+(int other) const { return IntWrapper(value_ + other); }
- bool operator<(const IntWrapper& other) const {
- return value_ < other.value_;
- }
- int value() const { return value_; }
-
- private:
- int value_;
-};
-
-TEST(RangeTest, WorksWithACustomTypeWithDifferentIncrementType) {
- const ParamGenerator<IntWrapper> gen = Range(IntWrapper(0), IntWrapper(2));
- ParamGenerator<IntWrapper>::iterator it = gen.begin();
-
- ASSERT_FALSE(it == gen.end());
- EXPECT_EQ(0, it->value());
-
- ASSERT_FALSE(++it == gen.end());
- EXPECT_EQ(1, it->value());
-
- EXPECT_TRUE(++it == gen.end());
-}
-
-// Tests that ValuesIn() with an array parameter generates
-// the expected sequence.
-TEST(ValuesInTest, ValuesInArray) {
- int array[] = {3, 5, 8};
- const ParamGenerator<int> gen = ValuesIn(array);
- VerifyGenerator(gen, array);
-}
-
-// Tests that ValuesIn() with a const array parameter generates
-// the expected sequence.
-TEST(ValuesInTest, ValuesInConstArray) {
- const int array[] = {3, 5, 8};
- const ParamGenerator<int> gen = ValuesIn(array);
- VerifyGenerator(gen, array);
-}
-
-// Edge case. Tests that ValuesIn() with an array parameter containing a
-// single element generates the single element sequence.
-TEST(ValuesInTest, ValuesInSingleElementArray) {
- int array[] = {42};
- const ParamGenerator<int> gen = ValuesIn(array);
- VerifyGenerator(gen, array);
-}
-
-// Tests that ValuesIn() generates the expected sequence for an STL
-// container (vector).
-TEST(ValuesInTest, ValuesInVector) {
- typedef ::std::vector<int> ContainerType;
- ContainerType values;
- values.push_back(3);
- values.push_back(5);
- values.push_back(8);
- const ParamGenerator<int> gen = ValuesIn(values);
-
- const int expected_values[] = {3, 5, 8};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that ValuesIn() generates the expected sequence.
-TEST(ValuesInTest, ValuesInIteratorRange) {
- typedef ::std::vector<int> ContainerType;
- ContainerType values;
- values.push_back(3);
- values.push_back(5);
- values.push_back(8);
- const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
-
- const int expected_values[] = {3, 5, 8};
- VerifyGenerator(gen, expected_values);
-}
-
-// Edge case. Tests that ValuesIn() provided with an iterator range specifying a
-// single value generates a single-element sequence.
-TEST(ValuesInTest, ValuesInSingleElementIteratorRange) {
- typedef ::std::vector<int> ContainerType;
- ContainerType values;
- values.push_back(42);
- const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
-
- const int expected_values[] = {42};
- VerifyGenerator(gen, expected_values);
-}
-
-// Edge case. Tests that ValuesIn() provided with an empty iterator range
-// generates an empty sequence.
-TEST(ValuesInTest, ValuesInEmptyIteratorRange) {
- typedef ::std::vector<int> ContainerType;
- ContainerType values;
- const ParamGenerator<int> gen = ValuesIn(values.begin(), values.end());
-
- VerifyGeneratorIsEmpty(gen);
-}
-
-// Tests that the Values() generates the expected sequence.
-TEST(ValuesTest, ValuesWorks) {
- const ParamGenerator<int> gen = Values(3, 5, 8);
-
- const int expected_values[] = {3, 5, 8};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that Values() generates the expected sequences from elements of
-// different types convertible to ParamGenerator's parameter type.
-TEST(ValuesTest, ValuesWorksForValuesOfCompatibleTypes) {
- const ParamGenerator<double> gen = Values(3, 5.0f, 8.0);
-
- const double expected_values[] = {3.0, 5.0, 8.0};
- VerifyGenerator(gen, expected_values);
-}
-
-TEST(ValuesTest, ValuesWorksForMaxLengthList) {
- const ParamGenerator<int> gen = Values(
- 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
- 110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
- 210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
- 310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
- 410, 420, 430, 440, 450, 460, 470, 480, 490, 500);
-
- const int expected_values[] = {
- 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
- 110, 120, 130, 140, 150, 160, 170, 180, 190, 200,
- 210, 220, 230, 240, 250, 260, 270, 280, 290, 300,
- 310, 320, 330, 340, 350, 360, 370, 380, 390, 400,
- 410, 420, 430, 440, 450, 460, 470, 480, 490, 500};
- VerifyGenerator(gen, expected_values);
-}
-
-// Edge case test. Tests that single-parameter Values() generates the sequence
-// with the single value.
-TEST(ValuesTest, ValuesWithSingleParameter) {
- const ParamGenerator<int> gen = Values(42);
-
- const int expected_values[] = {42};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that Bool() generates sequence (false, true).
-TEST(BoolTest, BoolWorks) {
- const ParamGenerator<bool> gen = Bool();
-
- const bool expected_values[] = {false, true};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that Combine() with two parameters generates the expected sequence.
-TEST(CombineTest, CombineWithTwoParameters) {
- const char* foo = "foo";
- const char* bar = "bar";
- const ParamGenerator<std::tuple<const char*, int> > gen =
- Combine(Values(foo, bar), Values(3, 4));
-
- std::tuple<const char*, int> expected_values[] = {
- std::make_tuple(foo, 3), std::make_tuple(foo, 4), std::make_tuple(bar, 3),
- std::make_tuple(bar, 4)};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that Combine() with three parameters generates the expected sequence.
-TEST(CombineTest, CombineWithThreeParameters) {
- const ParamGenerator<std::tuple<int, int, int> > gen =
- Combine(Values(0, 1), Values(3, 4), Values(5, 6));
- std::tuple<int, int, int> expected_values[] = {
- std::make_tuple(0, 3, 5), std::make_tuple(0, 3, 6),
- std::make_tuple(0, 4, 5), std::make_tuple(0, 4, 6),
- std::make_tuple(1, 3, 5), std::make_tuple(1, 3, 6),
- std::make_tuple(1, 4, 5), std::make_tuple(1, 4, 6)};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that the Combine() with the first parameter generating a single value
-// sequence generates a sequence with the number of elements equal to the
-// number of elements in the sequence generated by the second parameter.
-TEST(CombineTest, CombineWithFirstParameterSingleValue) {
- const ParamGenerator<std::tuple<int, int> > gen =
- Combine(Values(42), Values(0, 1));
-
- std::tuple<int, int> expected_values[] = {std::make_tuple(42, 0),
- std::make_tuple(42, 1)};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that the Combine() with the second parameter generating a single value
-// sequence generates a sequence with the number of elements equal to the
-// number of elements in the sequence generated by the first parameter.
-TEST(CombineTest, CombineWithSecondParameterSingleValue) {
- const ParamGenerator<std::tuple<int, int> > gen =
- Combine(Values(0, 1), Values(42));
-
- std::tuple<int, int> expected_values[] = {std::make_tuple(0, 42),
- std::make_tuple(1, 42)};
- VerifyGenerator(gen, expected_values);
-}
-
-// Tests that when the first parameter produces an empty sequence,
-// Combine() produces an empty sequence, too.
-TEST(CombineTest, CombineWithFirstParameterEmptyRange) {
- const ParamGenerator<std::tuple<int, int> > gen =
- Combine(Range(0, 0), Values(0, 1));
- VerifyGeneratorIsEmpty(gen);
-}
-
-// Tests that when the second parameter produces an empty sequence,
-// Combine() produces an empty sequence, too.
-TEST(CombineTest, CombineWithSecondParameterEmptyRange) {
- const ParamGenerator<std::tuple<int, int> > gen =
- Combine(Values(0, 1), Range(1, 1));
- VerifyGeneratorIsEmpty(gen);
-}
-
-// Edge case. Tests that combine works with the maximum number
-// of parameters supported by Google Test (currently 10).
-TEST(CombineTest, CombineWithMaxNumberOfParameters) {
- const char* foo = "foo";
- const char* bar = "bar";
- const ParamGenerator<
- std::tuple<const char*, int, int, int, int, int, int, int, int, int> >
- gen =
- Combine(Values(foo, bar), Values(1), Values(2), Values(3), Values(4),
- Values(5), Values(6), Values(7), Values(8), Values(9));
-
- std::tuple<const char*, int, int, int, int, int, int, int, int, int>
- expected_values[] = {std::make_tuple(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9),
- std::make_tuple(bar, 1, 2, 3, 4, 5, 6, 7, 8, 9)};
- VerifyGenerator(gen, expected_values);
-}
-
-class NonDefaultConstructAssignString {
- public:
- NonDefaultConstructAssignString(const std::string& s) : str_(s) {}
-
- const std::string& str() const { return str_; }
-
- private:
- std::string str_;
-
- // Not default constructible
- NonDefaultConstructAssignString();
- // Not assignable
- void operator=(const NonDefaultConstructAssignString&);
-};
-
-TEST(CombineTest, NonDefaultConstructAssign) {
- const ParamGenerator<std::tuple<int, NonDefaultConstructAssignString> > gen =
- Combine(Values(0, 1), Values(NonDefaultConstructAssignString("A"),
- NonDefaultConstructAssignString("B")));
-
- ParamGenerator<std::tuple<int, NonDefaultConstructAssignString> >::iterator
- it = gen.begin();
-
- EXPECT_EQ(0, std::get<0>(*it));
- EXPECT_EQ("A", std::get<1>(*it).str());
- ++it;
-
- EXPECT_EQ(0, std::get<0>(*it));
- EXPECT_EQ("B", std::get<1>(*it).str());
- ++it;
-
- EXPECT_EQ(1, std::get<0>(*it));
- EXPECT_EQ("A", std::get<1>(*it).str());
- ++it;
-
- EXPECT_EQ(1, std::get<0>(*it));
- EXPECT_EQ("B", std::get<1>(*it).str());
- ++it;
-
- EXPECT_TRUE(it == gen.end());
-}
-
-
-// Tests that an generator produces correct sequence after being
-// assigned from another generator.
-TEST(ParamGeneratorTest, AssignmentWorks) {
- ParamGenerator<int> gen = Values(1, 2);
- const ParamGenerator<int> gen2 = Values(3, 4);
- gen = gen2;
-
- const int expected_values[] = {3, 4};
- VerifyGenerator(gen, expected_values);
-}
-
-// This test verifies that the tests are expanded and run as specified:
-// one test per element from the sequence produced by the generator
-// specified in INSTANTIATE_TEST_SUITE_P. It also verifies that the test's
-// fixture constructor, SetUp(), and TearDown() have run and have been
-// supplied with the correct parameters.
-
-// The use of environment object allows detection of the case where no test
-// case functionality is run at all. In this case TearDownTestSuite will not
-// be able to detect missing tests, naturally.
-template <int kExpectedCalls>
-class TestGenerationEnvironment : public ::testing::Environment {
- public:
- static TestGenerationEnvironment* Instance() {
- static TestGenerationEnvironment* instance = new TestGenerationEnvironment;
- return instance;
- }
-
- void FixtureConstructorExecuted() { fixture_constructor_count_++; }
- void SetUpExecuted() { set_up_count_++; }
- void TearDownExecuted() { tear_down_count_++; }
- void TestBodyExecuted() { test_body_count_++; }
-
- void TearDown() override {
- // If all MultipleTestGenerationTest tests have been de-selected
- // by the filter flag, the following checks make no sense.
- bool perform_check = false;
-
- for (int i = 0; i < kExpectedCalls; ++i) {
- Message msg;
- msg << "TestsExpandedAndRun/" << i;
- if (UnitTestOptions::FilterMatchesTest(
- "TestExpansionModule/MultipleTestGenerationTest",
- msg.GetString().c_str())) {
- perform_check = true;
- }
- }
- if (perform_check) {
- EXPECT_EQ(kExpectedCalls, fixture_constructor_count_)
- << "Fixture constructor of ParamTestGenerationTest test case "
- << "has not been run as expected.";
- EXPECT_EQ(kExpectedCalls, set_up_count_)
- << "Fixture SetUp method of ParamTestGenerationTest test case "
- << "has not been run as expected.";
- EXPECT_EQ(kExpectedCalls, tear_down_count_)
- << "Fixture TearDown method of ParamTestGenerationTest test case "
- << "has not been run as expected.";
- EXPECT_EQ(kExpectedCalls, test_body_count_)
- << "Test in ParamTestGenerationTest test case "
- << "has not been run as expected.";
- }
- }
-
- private:
- TestGenerationEnvironment() : fixture_constructor_count_(0), set_up_count_(0),
- tear_down_count_(0), test_body_count_(0) {}
-
- int fixture_constructor_count_;
- int set_up_count_;
- int tear_down_count_;
- int test_body_count_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestGenerationEnvironment);
-};
-
-const int test_generation_params[] = {36, 42, 72};
-
-class TestGenerationTest : public TestWithParam<int> {
- public:
- enum {
- PARAMETER_COUNT =
- sizeof(test_generation_params)/sizeof(test_generation_params[0])
- };
-
- typedef TestGenerationEnvironment<PARAMETER_COUNT> Environment;
-
- TestGenerationTest() {
- Environment::Instance()->FixtureConstructorExecuted();
- current_parameter_ = GetParam();
- }
- void SetUp() override {
- Environment::Instance()->SetUpExecuted();
- EXPECT_EQ(current_parameter_, GetParam());
- }
- void TearDown() override {
- Environment::Instance()->TearDownExecuted();
- EXPECT_EQ(current_parameter_, GetParam());
- }
-
- static void SetUpTestSuite() {
- bool all_tests_in_test_case_selected = true;
-
- for (int i = 0; i < PARAMETER_COUNT; ++i) {
- Message test_name;
- test_name << "TestsExpandedAndRun/" << i;
- if ( !UnitTestOptions::FilterMatchesTest(
- "TestExpansionModule/MultipleTestGenerationTest",
- test_name.GetString())) {
- all_tests_in_test_case_selected = false;
- }
- }
- EXPECT_TRUE(all_tests_in_test_case_selected)
- << "When running the TestGenerationTest test case all of its tests\n"
- << "must be selected by the filter flag for the test case to pass.\n"
- << "If not all of them are enabled, we can't reliably conclude\n"
- << "that the correct number of tests have been generated.";
-
- collected_parameters_.clear();
- }
-
- static void TearDownTestSuite() {
- vector<int> expected_values(test_generation_params,
- test_generation_params + PARAMETER_COUNT);
- // Test execution order is not guaranteed by Google Test,
- // so the order of values in collected_parameters_ can be
- // different and we have to sort to compare.
- sort(expected_values.begin(), expected_values.end());
- sort(collected_parameters_.begin(), collected_parameters_.end());
-
- EXPECT_TRUE(collected_parameters_ == expected_values);
- }
-
- protected:
- int current_parameter_;
- static vector<int> collected_parameters_;
-
- private:
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestGenerationTest);
-};
-vector<int> TestGenerationTest::collected_parameters_;
-
-TEST_P(TestGenerationTest, TestsExpandedAndRun) {
- Environment::Instance()->TestBodyExecuted();
- EXPECT_EQ(current_parameter_, GetParam());
- collected_parameters_.push_back(GetParam());
-}
-INSTANTIATE_TEST_SUITE_P(TestExpansionModule, TestGenerationTest,
- ValuesIn(test_generation_params));
-
-// This test verifies that the element sequence (third parameter of
-// INSTANTIATE_TEST_SUITE_P) is evaluated in InitGoogleTest() and neither at
-// the call site of INSTANTIATE_TEST_SUITE_P nor in RUN_ALL_TESTS(). For
-// that, we declare param_value_ to be a static member of
-// GeneratorEvaluationTest and initialize it to 0. We set it to 1 in
-// main(), just before invocation of InitGoogleTest(). After calling
-// InitGoogleTest(), we set the value to 2. If the sequence is evaluated
-// before or after InitGoogleTest, INSTANTIATE_TEST_SUITE_P will create a
-// test with parameter other than 1, and the test body will fail the
-// assertion.
-class GeneratorEvaluationTest : public TestWithParam<int> {
- public:
- static int param_value() { return param_value_; }
- static void set_param_value(int param_value) { param_value_ = param_value; }
-
- private:
- static int param_value_;
-};
-int GeneratorEvaluationTest::param_value_ = 0;
-
-TEST_P(GeneratorEvaluationTest, GeneratorsEvaluatedInMain) {
- EXPECT_EQ(1, GetParam());
-}
-INSTANTIATE_TEST_SUITE_P(GenEvalModule, GeneratorEvaluationTest,
- Values(GeneratorEvaluationTest::param_value()));
-
-// Tests that generators defined in a different translation unit are
-// functional. Generator extern_gen is defined in gtest-param-test_test2.cc.
-extern ParamGenerator<int> extern_gen;
-class ExternalGeneratorTest : public TestWithParam<int> {};
-TEST_P(ExternalGeneratorTest, ExternalGenerator) {
- // Sequence produced by extern_gen contains only a single value
- // which we verify here.
- EXPECT_EQ(GetParam(), 33);
-}
-INSTANTIATE_TEST_SUITE_P(ExternalGeneratorModule, ExternalGeneratorTest,
- extern_gen);
-
-// Tests that a parameterized test case can be defined in one translation
-// unit and instantiated in another. This test will be instantiated in
-// gtest-param-test_test2.cc. ExternalInstantiationTest fixture class is
-// defined in gtest-param-test_test.h.
-TEST_P(ExternalInstantiationTest, IsMultipleOf33) {
- EXPECT_EQ(0, GetParam() % 33);
-}
-
-// Tests that a parameterized test case can be instantiated with multiple
-// generators.
-class MultipleInstantiationTest : public TestWithParam<int> {};
-TEST_P(MultipleInstantiationTest, AllowsMultipleInstances) {
-}
-INSTANTIATE_TEST_SUITE_P(Sequence1, MultipleInstantiationTest, Values(1, 2));
-INSTANTIATE_TEST_SUITE_P(Sequence2, MultipleInstantiationTest, Range(3, 5));
-
-// Tests that a parameterized test case can be instantiated
-// in multiple translation units. This test will be instantiated
-// here and in gtest-param-test_test2.cc.
-// InstantiationInMultipleTranslationUnitsTest fixture class
-// is defined in gtest-param-test_test.h.
-TEST_P(InstantiationInMultipleTranslationUnitsTest, IsMultipleOf42) {
- EXPECT_EQ(0, GetParam() % 42);
-}
-INSTANTIATE_TEST_SUITE_P(Sequence1, InstantiationInMultipleTranslationUnitsTest,
- Values(42, 42 * 2));
-
-// Tests that each iteration of parameterized test runs in a separate test
-// object.
-class SeparateInstanceTest : public TestWithParam<int> {
- public:
- SeparateInstanceTest() : count_(0) {}
-
- static void TearDownTestSuite() {
- EXPECT_GE(global_count_, 2)
- << "If some (but not all) SeparateInstanceTest tests have been "
- << "filtered out this test will fail. Make sure that all "
- << "GeneratorEvaluationTest are selected or de-selected together "
- << "by the test filter.";
- }
-
- protected:
- int count_;
- static int global_count_;
-};
-int SeparateInstanceTest::global_count_ = 0;
-
-TEST_P(SeparateInstanceTest, TestsRunInSeparateInstances) {
- EXPECT_EQ(0, count_++);
- global_count_++;
-}
-INSTANTIATE_TEST_SUITE_P(FourElemSequence, SeparateInstanceTest, Range(1, 4));
-
-// Tests that all instantiations of a test have named appropriately. Test
-// defined with TEST_P(TestSuiteName, TestName) and instantiated with
-// INSTANTIATE_TEST_SUITE_P(SequenceName, TestSuiteName, generator) must be
-// named SequenceName/TestSuiteName.TestName/i, where i is the 0-based index of
-// the sequence element used to instantiate the test.
-class NamingTest : public TestWithParam<int> {};
-
-TEST_P(NamingTest, TestsReportCorrectNamesAndParameters) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
-
- EXPECT_STREQ("ZeroToFiveSequence/NamingTest", test_info->test_suite_name());
-
- Message index_stream;
- index_stream << "TestsReportCorrectNamesAndParameters/" << GetParam();
- EXPECT_STREQ(index_stream.GetString().c_str(), test_info->name());
-
- EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
-}
-
-INSTANTIATE_TEST_SUITE_P(ZeroToFiveSequence, NamingTest, Range(0, 5));
-
-// Tests that macros in test names are expanded correctly.
-class MacroNamingTest : public TestWithParam<int> {};
-
-#define PREFIX_WITH_FOO(test_name) Foo##test_name
-#define PREFIX_WITH_MACRO(test_name) Macro##test_name
-
-TEST_P(PREFIX_WITH_MACRO(NamingTest), PREFIX_WITH_FOO(SomeTestName)) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
-
- EXPECT_STREQ("FortyTwo/MacroNamingTest", test_info->test_suite_name());
- EXPECT_STREQ("FooSomeTestName", test_info->name());
-}
-
-INSTANTIATE_TEST_SUITE_P(FortyTwo, MacroNamingTest, Values(42));
-
-// Tests the same thing for non-parametrized tests.
-class MacroNamingTestNonParametrized : public ::testing::Test {};
-
-TEST_F(PREFIX_WITH_MACRO(NamingTestNonParametrized),
- PREFIX_WITH_FOO(SomeTestName)) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
-
- EXPECT_STREQ("MacroNamingTestNonParametrized", test_info->test_suite_name());
- EXPECT_STREQ("FooSomeTestName", test_info->name());
-}
-
-// Tests that user supplied custom parameter names are working correctly.
-// Runs the test with a builtin helper method which uses PrintToString,
-// as well as a custom function and custom functor to ensure all possible
-// uses work correctly.
-class CustomFunctorNamingTest : public TestWithParam<std::string> {};
-TEST_P(CustomFunctorNamingTest, CustomTestNames) {}
-
-struct CustomParamNameFunctor {
- std::string operator()(const ::testing::TestParamInfo<std::string>& inf) {
- return inf.param;
- }
-};
-
-INSTANTIATE_TEST_SUITE_P(CustomParamNameFunctor, CustomFunctorNamingTest,
- Values(std::string("FunctorName")),
- CustomParamNameFunctor());
-
-INSTANTIATE_TEST_SUITE_P(AllAllowedCharacters, CustomFunctorNamingTest,
- Values("abcdefghijklmnopqrstuvwxyz",
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "01234567890_"),
- CustomParamNameFunctor());
-
-inline std::string CustomParamNameFunction(
- const ::testing::TestParamInfo<std::string>& inf) {
- return inf.param;
-}
-
-class CustomFunctionNamingTest : public TestWithParam<std::string> {};
-TEST_P(CustomFunctionNamingTest, CustomTestNames) {}
-
-INSTANTIATE_TEST_SUITE_P(CustomParamNameFunction, CustomFunctionNamingTest,
- Values(std::string("FunctionName")),
- CustomParamNameFunction);
-
-INSTANTIATE_TEST_SUITE_P(CustomParamNameFunctionP, CustomFunctionNamingTest,
- Values(std::string("FunctionNameP")),
- &CustomParamNameFunction);
-
-// Test custom naming with a lambda
-
-class CustomLambdaNamingTest : public TestWithParam<std::string> {};
-TEST_P(CustomLambdaNamingTest, CustomTestNames) {}
-
-INSTANTIATE_TEST_SUITE_P(CustomParamNameLambda, CustomLambdaNamingTest,
- Values(std::string("LambdaName")),
- [](const ::testing::TestParamInfo<std::string>& inf) {
- return inf.param;
- });
-
-TEST(CustomNamingTest, CheckNameRegistry) {
- ::testing::UnitTest* unit_test = ::testing::UnitTest::GetInstance();
- std::set<std::string> test_names;
- for (int suite_num = 0; suite_num < unit_test->total_test_suite_count();
- ++suite_num) {
- const ::testing::TestSuite* test_suite = unit_test->GetTestSuite(suite_num);
- for (int test_num = 0; test_num < test_suite->total_test_count();
- ++test_num) {
- const ::testing::TestInfo* test_info = test_suite->GetTestInfo(test_num);
- test_names.insert(std::string(test_info->name()));
- }
- }
- EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctorName"));
- EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctionName"));
- EXPECT_EQ(1u, test_names.count("CustomTestNames/FunctionNameP"));
- EXPECT_EQ(1u, test_names.count("CustomTestNames/LambdaName"));
-}
-
-// Test a numeric name to ensure PrintToStringParamName works correctly.
-
-class CustomIntegerNamingTest : public TestWithParam<int> {};
-
-TEST_P(CustomIntegerNamingTest, TestsReportCorrectNames) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- Message test_name_stream;
- test_name_stream << "TestsReportCorrectNames/" << GetParam();
- EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
-}
-
-INSTANTIATE_TEST_SUITE_P(PrintToString, CustomIntegerNamingTest, Range(0, 5),
- ::testing::PrintToStringParamName());
-
-// Test a custom struct with PrintToString.
-
-struct CustomStruct {
- explicit CustomStruct(int value) : x(value) {}
- int x;
-};
-
-std::ostream& operator<<(std::ostream& stream, const CustomStruct& val) {
- stream << val.x;
- return stream;
-}
-
-class CustomStructNamingTest : public TestWithParam<CustomStruct> {};
-
-TEST_P(CustomStructNamingTest, TestsReportCorrectNames) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- Message test_name_stream;
- test_name_stream << "TestsReportCorrectNames/" << GetParam();
- EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
-}
-
-INSTANTIATE_TEST_SUITE_P(PrintToString, CustomStructNamingTest,
- Values(CustomStruct(0), CustomStruct(1)),
- ::testing::PrintToStringParamName());
-
-// Test that using a stateful parameter naming function works as expected.
-
-struct StatefulNamingFunctor {
- StatefulNamingFunctor() : sum(0) {}
- std::string operator()(const ::testing::TestParamInfo<int>& info) {
- int value = info.param + sum;
- sum += info.param;
- return ::testing::PrintToString(value);
- }
- int sum;
-};
-
-class StatefulNamingTest : public ::testing::TestWithParam<int> {
- protected:
- StatefulNamingTest() : sum_(0) {}
- int sum_;
-};
-
-TEST_P(StatefulNamingTest, TestsReportCorrectNames) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
- sum_ += GetParam();
- Message test_name_stream;
- test_name_stream << "TestsReportCorrectNames/" << sum_;
- EXPECT_STREQ(test_name_stream.GetString().c_str(), test_info->name());
-}
-
-INSTANTIATE_TEST_SUITE_P(StatefulNamingFunctor, StatefulNamingTest, Range(0, 5),
- StatefulNamingFunctor());
-
-// Class that cannot be streamed into an ostream. It needs to be copyable
-// (and, in case of MSVC, also assignable) in order to be a test parameter
-// type. Its default copy constructor and assignment operator do exactly
-// what we need.
-class Unstreamable {
- public:
- explicit Unstreamable(int value) : value_(value) {}
- // -Wunused-private-field: dummy accessor for `value_`.
- const int& dummy_value() const { return value_; }
-
- private:
- int value_;
-};
-
-class CommentTest : public TestWithParam<Unstreamable> {};
-
-TEST_P(CommentTest, TestsCorrectlyReportUnstreamableParams) {
- const ::testing::TestInfo* const test_info =
- ::testing::UnitTest::GetInstance()->current_test_info();
-
- EXPECT_EQ(::testing::PrintToString(GetParam()), test_info->value_param());
-}
-
-INSTANTIATE_TEST_SUITE_P(InstantiationWithComments, CommentTest,
- Values(Unstreamable(1)));
-
-// Verify that we can create a hierarchy of test fixtures, where the base
-// class fixture is not parameterized and the derived class is. In this case
-// ParameterizedDerivedTest inherits from NonParameterizedBaseTest. We
-// perform simple tests on both.
-class NonParameterizedBaseTest : public ::testing::Test {
- public:
- NonParameterizedBaseTest() : n_(17) { }
- protected:
- int n_;
-};
-
-class ParameterizedDerivedTest : public NonParameterizedBaseTest,
- public ::testing::WithParamInterface<int> {
- protected:
- ParameterizedDerivedTest() : count_(0) { }
- int count_;
- static int global_count_;
-};
-
-int ParameterizedDerivedTest::global_count_ = 0;
-
-TEST_F(NonParameterizedBaseTest, FixtureIsInitialized) {
- EXPECT_EQ(17, n_);
-}
-
-TEST_P(ParameterizedDerivedTest, SeesSequence) {
- EXPECT_EQ(17, n_);
- EXPECT_EQ(0, count_++);
- EXPECT_EQ(GetParam(), global_count_++);
-}
-
-class ParameterizedDeathTest : public ::testing::TestWithParam<int> { };
-
-TEST_F(ParameterizedDeathTest, GetParamDiesFromTestF) {
- EXPECT_DEATH_IF_SUPPORTED(GetParam(),
- ".* value-parameterized test .*");
-}
-
-INSTANTIATE_TEST_SUITE_P(RangeZeroToFive, ParameterizedDerivedTest,
- Range(0, 5));
-
-// Tests param generator working with Enums
-enum MyEnums {
- ENUM1 = 1,
- ENUM2 = 3,
- ENUM3 = 8,
-};
-
-class MyEnumTest : public testing::TestWithParam<MyEnums> {};
-
-TEST_P(MyEnumTest, ChecksParamMoreThanZero) { EXPECT_GE(10, GetParam()); }
-INSTANTIATE_TEST_SUITE_P(MyEnumTests, MyEnumTest,
- ::testing::Values(ENUM1, ENUM2, 0));
-
-int main(int argc, char **argv) {
- // Used in TestGenerationTest test suite.
- AddGlobalTestEnvironment(TestGenerationTest::Environment::Instance());
- // Used in GeneratorEvaluationTest test suite. Tests that the updated value
- // will be picked up for instantiating tests in GeneratorEvaluationTest.
- GeneratorEvaluationTest::set_param_value(1);
-
- ::testing::InitGoogleTest(&argc, argv);
-
- // Used in GeneratorEvaluationTest test suite. Tests that value updated
- // here will NOT be used for instantiating tests in
- // GeneratorEvaluationTest.
- GeneratorEvaluationTest::set_param_value(2);
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This header file provides classes and functions used internally
-// for testing Google Test itself.
-
-#ifndef GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
-#define GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
-
-#include "gtest/gtest.h"
-
-// Test fixture for testing definition and instantiation of a test
-// in separate translation units.
-class ExternalInstantiationTest : public ::testing::TestWithParam<int> {
-};
-
-// Test fixture for testing instantiation of a test in multiple
-// translation units.
-class InstantiationInMultipleTranslationUnitsTest
- : public ::testing::TestWithParam<int> {
-};
-
-#endif // GTEST_TEST_GTEST_PARAM_TEST_TEST_H_
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for Google Test itself. This verifies that the basic constructs of
-// Google Test work.
-
-#include "gtest/gtest.h"
-#include "test/googletest-param-test-test.h"
-
-using ::testing::Values;
-using ::testing::internal::ParamGenerator;
-
-// Tests that generators defined in a different translation unit
-// are functional. The test using extern_gen is defined
-// in googletest-param-test-test.cc.
-ParamGenerator<int> extern_gen = Values(33);
-
-// Tests that a parameterized test case can be defined in one translation unit
-// and instantiated in another. The test is defined in
-// googletest-param-test-test.cc and ExternalInstantiationTest fixture class is
-// defined in gtest-param-test_test.h.
-INSTANTIATE_TEST_SUITE_P(MultiplesOf33,
- ExternalInstantiationTest,
- Values(33, 66));
-
-// Tests that a parameterized test case can be instantiated
-// in multiple translation units. Another instantiation is defined
-// in googletest-param-test-test.cc and
-// InstantiationInMultipleTranslationUnitsTest fixture is defined in
-// gtest-param-test_test.h
-INSTANTIATE_TEST_SUITE_P(Sequence2,
- InstantiationInMultipleTranslationUnitsTest,
- Values(42*3, 42*4, 42*5));
-
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// This file tests the internal cross-platform support utilities.
-#include <stdio.h>
-
-#include "gtest/internal/gtest-port.h"
-
-#if GTEST_OS_MAC
-# include <time.h>
-#endif // GTEST_OS_MAC
-
-#include <list>
-#include <memory>
-#include <utility> // For std::pair and std::make_pair.
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "gtest/gtest-spi.h"
-#include "src/gtest-internal-inl.h"
-
-using std::make_pair;
-using std::pair;
-
-namespace testing {
-namespace internal {
-
-TEST(IsXDigitTest, WorksForNarrowAscii) {
- EXPECT_TRUE(IsXDigit('0'));
- EXPECT_TRUE(IsXDigit('9'));
- EXPECT_TRUE(IsXDigit('A'));
- EXPECT_TRUE(IsXDigit('F'));
- EXPECT_TRUE(IsXDigit('a'));
- EXPECT_TRUE(IsXDigit('f'));
-
- EXPECT_FALSE(IsXDigit('-'));
- EXPECT_FALSE(IsXDigit('g'));
- EXPECT_FALSE(IsXDigit('G'));
-}
-
-TEST(IsXDigitTest, ReturnsFalseForNarrowNonAscii) {
- EXPECT_FALSE(IsXDigit(static_cast<char>('\x80')));
- EXPECT_FALSE(IsXDigit(static_cast<char>('0' | '\x80')));
-}
-
-TEST(IsXDigitTest, WorksForWideAscii) {
- EXPECT_TRUE(IsXDigit(L'0'));
- EXPECT_TRUE(IsXDigit(L'9'));
- EXPECT_TRUE(IsXDigit(L'A'));
- EXPECT_TRUE(IsXDigit(L'F'));
- EXPECT_TRUE(IsXDigit(L'a'));
- EXPECT_TRUE(IsXDigit(L'f'));
-
- EXPECT_FALSE(IsXDigit(L'-'));
- EXPECT_FALSE(IsXDigit(L'g'));
- EXPECT_FALSE(IsXDigit(L'G'));
-}
-
-TEST(IsXDigitTest, ReturnsFalseForWideNonAscii) {
- EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(0x80)));
- EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x80)));
- EXPECT_FALSE(IsXDigit(static_cast<wchar_t>(L'0' | 0x100)));
-}
-
-class Base {
- public:
- // Copy constructor and assignment operator do exactly what we need, so we
- // use them.
- Base() : member_(0) {}
- explicit Base(int n) : member_(n) {}
- virtual ~Base() {}
- int member() { return member_; }
-
- private:
- int member_;
-};
-
-class Derived : public Base {
- public:
- explicit Derived(int n) : Base(n) {}
-};
-
-TEST(ImplicitCastTest, ConvertsPointers) {
- Derived derived(0);
- EXPECT_TRUE(&derived == ::testing::internal::ImplicitCast_<Base*>(&derived));
-}
-
-TEST(ImplicitCastTest, CanUseInheritance) {
- Derived derived(1);
- Base base = ::testing::internal::ImplicitCast_<Base>(derived);
- EXPECT_EQ(derived.member(), base.member());
-}
-
-class Castable {
- public:
- explicit Castable(bool* converted) : converted_(converted) {}
- operator Base() {
- *converted_ = true;
- return Base();
- }
-
- private:
- bool* converted_;
-};
-
-TEST(ImplicitCastTest, CanUseNonConstCastOperator) {
- bool converted = false;
- Castable castable(&converted);
- Base base = ::testing::internal::ImplicitCast_<Base>(castable);
- EXPECT_TRUE(converted);
-}
-
-class ConstCastable {
- public:
- explicit ConstCastable(bool* converted) : converted_(converted) {}
- operator Base() const {
- *converted_ = true;
- return Base();
- }
-
- private:
- bool* converted_;
-};
-
-TEST(ImplicitCastTest, CanUseConstCastOperatorOnConstValues) {
- bool converted = false;
- const ConstCastable const_castable(&converted);
- Base base = ::testing::internal::ImplicitCast_<Base>(const_castable);
- EXPECT_TRUE(converted);
-}
-
-class ConstAndNonConstCastable {
- public:
- ConstAndNonConstCastable(bool* converted, bool* const_converted)
- : converted_(converted), const_converted_(const_converted) {}
- operator Base() {
- *converted_ = true;
- return Base();
- }
- operator Base() const {
- *const_converted_ = true;
- return Base();
- }
-
- private:
- bool* converted_;
- bool* const_converted_;
-};
-
-TEST(ImplicitCastTest, CanSelectBetweenConstAndNonConstCasrAppropriately) {
- bool converted = false;
- bool const_converted = false;
- ConstAndNonConstCastable castable(&converted, &const_converted);
- Base base = ::testing::internal::ImplicitCast_<Base>(castable);
- EXPECT_TRUE(converted);
- EXPECT_FALSE(const_converted);
-
- converted = false;
- const_converted = false;
- const ConstAndNonConstCastable const_castable(&converted, &const_converted);
- base = ::testing::internal::ImplicitCast_<Base>(const_castable);
- EXPECT_FALSE(converted);
- EXPECT_TRUE(const_converted);
-}
-
-class To {
- public:
- To(bool* converted) { *converted = true; } // NOLINT
-};
-
-TEST(ImplicitCastTest, CanUseImplicitConstructor) {
- bool converted = false;
- To to = ::testing::internal::ImplicitCast_<To>(&converted);
- (void)to;
- EXPECT_TRUE(converted);
-}
-
-TEST(GtestCheckSyntaxTest, BehavesLikeASingleStatement) {
- if (AlwaysFalse())
- GTEST_CHECK_(false) << "This should never be executed; "
- "It's a compilation test only.";
-
- if (AlwaysTrue())
- GTEST_CHECK_(true);
- else
- ; // NOLINT
-
- if (AlwaysFalse())
- ; // NOLINT
- else
- GTEST_CHECK_(true) << "";
-}
-
-TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
- switch (0) {
- case 1:
- break;
- default:
- GTEST_CHECK_(true);
- }
-
- switch (0)
- case 0:
- GTEST_CHECK_(true) << "Check failed in switch case";
-}
-
-// Verifies behavior of FormatFileLocation.
-TEST(FormatFileLocationTest, FormatsFileLocation) {
- EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42));
- EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42));
-}
-
-TEST(FormatFileLocationTest, FormatsUnknownFile) {
- EXPECT_PRED_FORMAT2(IsSubstring, "unknown file",
- FormatFileLocation(nullptr, 42));
- EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation(nullptr, 42));
-}
-
-TEST(FormatFileLocationTest, FormatsUknownLine) {
- EXPECT_EQ("foo.cc:", FormatFileLocation("foo.cc", -1));
-}
-
-TEST(FormatFileLocationTest, FormatsUknownFileAndLine) {
- EXPECT_EQ("unknown file:", FormatFileLocation(nullptr, -1));
-}
-
-// Verifies behavior of FormatCompilerIndependentFileLocation.
-TEST(FormatCompilerIndependentFileLocationTest, FormatsFileLocation) {
- EXPECT_EQ("foo.cc:42", FormatCompilerIndependentFileLocation("foo.cc", 42));
-}
-
-TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFile) {
- EXPECT_EQ("unknown file:42",
- FormatCompilerIndependentFileLocation(nullptr, 42));
-}
-
-TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) {
- EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1));
-}
-
-TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
- EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1));
-}
-
-#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA || \
- GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
- GTEST_OS_NETBSD || GTEST_OS_OPENBSD
-void* ThreadFunc(void* data) {
- internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
- mutex->Lock();
- mutex->Unlock();
- return nullptr;
-}
-
-TEST(GetThreadCountTest, ReturnsCorrectValue) {
- const size_t starting_count = GetThreadCount();
- pthread_t thread_id;
-
- internal::Mutex mutex;
- {
- internal::MutexLock lock(&mutex);
- pthread_attr_t attr;
- ASSERT_EQ(0, pthread_attr_init(&attr));
- ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
-
- const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
- ASSERT_EQ(0, pthread_attr_destroy(&attr));
- ASSERT_EQ(0, status);
- EXPECT_EQ(starting_count + 1, GetThreadCount());
- }
-
- void* dummy;
- ASSERT_EQ(0, pthread_join(thread_id, &dummy));
-
- // The OS may not immediately report the updated thread count after
- // joining a thread, causing flakiness in this test. To counter that, we
- // wait for up to .5 seconds for the OS to report the correct value.
- for (int i = 0; i < 5; ++i) {
- if (GetThreadCount() == starting_count)
- break;
-
- SleepMilliseconds(100);
- }
-
- EXPECT_EQ(starting_count, GetThreadCount());
-}
-#else
-TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
- EXPECT_EQ(0U, GetThreadCount());
-}
-#endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA
-
-TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
- const bool a_false_condition = false;
- const char regex[] =
-#ifdef _MSC_VER
- "googletest-port-test\\.cc\\(\\d+\\):"
-#elif GTEST_USES_POSIX_RE
- "googletest-port-test\\.cc:[0-9]+"
-#else
- "googletest-port-test\\.cc:\\d+"
-#endif // _MSC_VER
- ".*a_false_condition.*Extra info.*";
-
- EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
- regex);
-}
-
-#if GTEST_HAS_DEATH_TEST
-
-TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
- EXPECT_EXIT({
- GTEST_CHECK_(true) << "Extra info";
- ::std::cerr << "Success\n";
- exit(0); },
- ::testing::ExitedWithCode(0), "Success");
-}
-
-#endif // GTEST_HAS_DEATH_TEST
-
-// Verifies that Google Test choose regular expression engine appropriate to
-// the platform. The test will produce compiler errors in case of failure.
-// For simplicity, we only cover the most important platforms here.
-TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) {
-#if !GTEST_USES_PCRE
-# if GTEST_HAS_POSIX_RE
-
- EXPECT_TRUE(GTEST_USES_POSIX_RE);
-
-# else
-
- EXPECT_TRUE(GTEST_USES_SIMPLE_RE);
-
-# endif
-#endif // !GTEST_USES_PCRE
-}
-
-#if GTEST_USES_POSIX_RE
-
-# if GTEST_HAS_TYPED_TEST
-
-template <typename Str>
-class RETest : public ::testing::Test {};
-
-// Defines StringTypes as the list of all string types that class RE
-// supports.
-typedef testing::Types< ::std::string, const char*> StringTypes;
-
-TYPED_TEST_SUITE(RETest, StringTypes);
-
-// Tests RE's implicit constructors.
-TYPED_TEST(RETest, ImplicitConstructorWorks) {
- const RE empty(TypeParam(""));
- EXPECT_STREQ("", empty.pattern());
-
- const RE simple(TypeParam("hello"));
- EXPECT_STREQ("hello", simple.pattern());
-
- const RE normal(TypeParam(".*(\\w+)"));
- EXPECT_STREQ(".*(\\w+)", normal.pattern());
-}
-
-// Tests that RE's constructors reject invalid regular expressions.
-TYPED_TEST(RETest, RejectsInvalidRegex) {
- EXPECT_NONFATAL_FAILURE({
- const RE invalid(TypeParam("?"));
- }, "\"?\" is not a valid POSIX Extended regular expression.");
-}
-
-// Tests RE::FullMatch().
-TYPED_TEST(RETest, FullMatchWorks) {
- const RE empty(TypeParam(""));
- EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty));
- EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty));
-
- const RE re(TypeParam("a.*z"));
- EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re));
- EXPECT_TRUE(RE::FullMatch(TypeParam("axyz"), re));
- EXPECT_FALSE(RE::FullMatch(TypeParam("baz"), re));
- EXPECT_FALSE(RE::FullMatch(TypeParam("azy"), re));
-}
-
-// Tests RE::PartialMatch().
-TYPED_TEST(RETest, PartialMatchWorks) {
- const RE empty(TypeParam(""));
- EXPECT_TRUE(RE::PartialMatch(TypeParam(""), empty));
- EXPECT_TRUE(RE::PartialMatch(TypeParam("a"), empty));
-
- const RE re(TypeParam("a.*z"));
- EXPECT_TRUE(RE::PartialMatch(TypeParam("az"), re));
- EXPECT_TRUE(RE::PartialMatch(TypeParam("axyz"), re));
- EXPECT_TRUE(RE::PartialMatch(TypeParam("baz"), re));
- EXPECT_TRUE(RE::PartialMatch(TypeParam("azy"), re));
- EXPECT_FALSE(RE::PartialMatch(TypeParam("zza"), re));
-}
-
-# endif // GTEST_HAS_TYPED_TEST
-
-#elif GTEST_USES_SIMPLE_RE
-
-TEST(IsInSetTest, NulCharIsNotInAnySet) {
- EXPECT_FALSE(IsInSet('\0', ""));
- EXPECT_FALSE(IsInSet('\0', "\0"));
- EXPECT_FALSE(IsInSet('\0', "a"));
-}
-
-TEST(IsInSetTest, WorksForNonNulChars) {
- EXPECT_FALSE(IsInSet('a', "Ab"));
- EXPECT_FALSE(IsInSet('c', ""));
-
- EXPECT_TRUE(IsInSet('b', "bcd"));
- EXPECT_TRUE(IsInSet('b', "ab"));
-}
-
-TEST(IsAsciiDigitTest, IsFalseForNonDigit) {
- EXPECT_FALSE(IsAsciiDigit('\0'));
- EXPECT_FALSE(IsAsciiDigit(' '));
- EXPECT_FALSE(IsAsciiDigit('+'));
- EXPECT_FALSE(IsAsciiDigit('-'));
- EXPECT_FALSE(IsAsciiDigit('.'));
- EXPECT_FALSE(IsAsciiDigit('a'));
-}
-
-TEST(IsAsciiDigitTest, IsTrueForDigit) {
- EXPECT_TRUE(IsAsciiDigit('0'));
- EXPECT_TRUE(IsAsciiDigit('1'));
- EXPECT_TRUE(IsAsciiDigit('5'));
- EXPECT_TRUE(IsAsciiDigit('9'));
-}
-
-TEST(IsAsciiPunctTest, IsFalseForNonPunct) {
- EXPECT_FALSE(IsAsciiPunct('\0'));
- EXPECT_FALSE(IsAsciiPunct(' '));
- EXPECT_FALSE(IsAsciiPunct('\n'));
- EXPECT_FALSE(IsAsciiPunct('a'));
- EXPECT_FALSE(IsAsciiPunct('0'));
-}
-
-TEST(IsAsciiPunctTest, IsTrueForPunct) {
- for (const char* p = "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~"; *p; p++) {
- EXPECT_PRED1(IsAsciiPunct, *p);
- }
-}
-
-TEST(IsRepeatTest, IsFalseForNonRepeatChar) {
- EXPECT_FALSE(IsRepeat('\0'));
- EXPECT_FALSE(IsRepeat(' '));
- EXPECT_FALSE(IsRepeat('a'));
- EXPECT_FALSE(IsRepeat('1'));
- EXPECT_FALSE(IsRepeat('-'));
-}
-
-TEST(IsRepeatTest, IsTrueForRepeatChar) {
- EXPECT_TRUE(IsRepeat('?'));
- EXPECT_TRUE(IsRepeat('*'));
- EXPECT_TRUE(IsRepeat('+'));
-}
-
-TEST(IsAsciiWhiteSpaceTest, IsFalseForNonWhiteSpace) {
- EXPECT_FALSE(IsAsciiWhiteSpace('\0'));
- EXPECT_FALSE(IsAsciiWhiteSpace('a'));
- EXPECT_FALSE(IsAsciiWhiteSpace('1'));
- EXPECT_FALSE(IsAsciiWhiteSpace('+'));
- EXPECT_FALSE(IsAsciiWhiteSpace('_'));
-}
-
-TEST(IsAsciiWhiteSpaceTest, IsTrueForWhiteSpace) {
- EXPECT_TRUE(IsAsciiWhiteSpace(' '));
- EXPECT_TRUE(IsAsciiWhiteSpace('\n'));
- EXPECT_TRUE(IsAsciiWhiteSpace('\r'));
- EXPECT_TRUE(IsAsciiWhiteSpace('\t'));
- EXPECT_TRUE(IsAsciiWhiteSpace('\v'));
- EXPECT_TRUE(IsAsciiWhiteSpace('\f'));
-}
-
-TEST(IsAsciiWordCharTest, IsFalseForNonWordChar) {
- EXPECT_FALSE(IsAsciiWordChar('\0'));
- EXPECT_FALSE(IsAsciiWordChar('+'));
- EXPECT_FALSE(IsAsciiWordChar('.'));
- EXPECT_FALSE(IsAsciiWordChar(' '));
- EXPECT_FALSE(IsAsciiWordChar('\n'));
-}
-
-TEST(IsAsciiWordCharTest, IsTrueForLetter) {
- EXPECT_TRUE(IsAsciiWordChar('a'));
- EXPECT_TRUE(IsAsciiWordChar('b'));
- EXPECT_TRUE(IsAsciiWordChar('A'));
- EXPECT_TRUE(IsAsciiWordChar('Z'));
-}
-
-TEST(IsAsciiWordCharTest, IsTrueForDigit) {
- EXPECT_TRUE(IsAsciiWordChar('0'));
- EXPECT_TRUE(IsAsciiWordChar('1'));
- EXPECT_TRUE(IsAsciiWordChar('7'));
- EXPECT_TRUE(IsAsciiWordChar('9'));
-}
-
-TEST(IsAsciiWordCharTest, IsTrueForUnderscore) {
- EXPECT_TRUE(IsAsciiWordChar('_'));
-}
-
-TEST(IsValidEscapeTest, IsFalseForNonPrintable) {
- EXPECT_FALSE(IsValidEscape('\0'));
- EXPECT_FALSE(IsValidEscape('\007'));
-}
-
-TEST(IsValidEscapeTest, IsFalseForDigit) {
- EXPECT_FALSE(IsValidEscape('0'));
- EXPECT_FALSE(IsValidEscape('9'));
-}
-
-TEST(IsValidEscapeTest, IsFalseForWhiteSpace) {
- EXPECT_FALSE(IsValidEscape(' '));
- EXPECT_FALSE(IsValidEscape('\n'));
-}
-
-TEST(IsValidEscapeTest, IsFalseForSomeLetter) {
- EXPECT_FALSE(IsValidEscape('a'));
- EXPECT_FALSE(IsValidEscape('Z'));
-}
-
-TEST(IsValidEscapeTest, IsTrueForPunct) {
- EXPECT_TRUE(IsValidEscape('.'));
- EXPECT_TRUE(IsValidEscape('-'));
- EXPECT_TRUE(IsValidEscape('^'));
- EXPECT_TRUE(IsValidEscape('$'));
- EXPECT_TRUE(IsValidEscape('('));
- EXPECT_TRUE(IsValidEscape(']'));
- EXPECT_TRUE(IsValidEscape('{'));
- EXPECT_TRUE(IsValidEscape('|'));
-}
-
-TEST(IsValidEscapeTest, IsTrueForSomeLetter) {
- EXPECT_TRUE(IsValidEscape('d'));
- EXPECT_TRUE(IsValidEscape('D'));
- EXPECT_TRUE(IsValidEscape('s'));
- EXPECT_TRUE(IsValidEscape('S'));
- EXPECT_TRUE(IsValidEscape('w'));
- EXPECT_TRUE(IsValidEscape('W'));
-}
-
-TEST(AtomMatchesCharTest, EscapedPunct) {
- EXPECT_FALSE(AtomMatchesChar(true, '\\', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, '\\', ' '));
- EXPECT_FALSE(AtomMatchesChar(true, '_', '.'));
- EXPECT_FALSE(AtomMatchesChar(true, '.', 'a'));
-
- EXPECT_TRUE(AtomMatchesChar(true, '\\', '\\'));
- EXPECT_TRUE(AtomMatchesChar(true, '_', '_'));
- EXPECT_TRUE(AtomMatchesChar(true, '+', '+'));
- EXPECT_TRUE(AtomMatchesChar(true, '.', '.'));
-}
-
-TEST(AtomMatchesCharTest, Escaped_d) {
- EXPECT_FALSE(AtomMatchesChar(true, 'd', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'd', 'a'));
- EXPECT_FALSE(AtomMatchesChar(true, 'd', '.'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 'd', '0'));
- EXPECT_TRUE(AtomMatchesChar(true, 'd', '9'));
-}
-
-TEST(AtomMatchesCharTest, Escaped_D) {
- EXPECT_FALSE(AtomMatchesChar(true, 'D', '0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'D', '9'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 'D', '\0'));
- EXPECT_TRUE(AtomMatchesChar(true, 'D', 'a'));
- EXPECT_TRUE(AtomMatchesChar(true, 'D', '-'));
-}
-
-TEST(AtomMatchesCharTest, Escaped_s) {
- EXPECT_FALSE(AtomMatchesChar(true, 's', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 's', 'a'));
- EXPECT_FALSE(AtomMatchesChar(true, 's', '.'));
- EXPECT_FALSE(AtomMatchesChar(true, 's', '9'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 's', ' '));
- EXPECT_TRUE(AtomMatchesChar(true, 's', '\n'));
- EXPECT_TRUE(AtomMatchesChar(true, 's', '\t'));
-}
-
-TEST(AtomMatchesCharTest, Escaped_S) {
- EXPECT_FALSE(AtomMatchesChar(true, 'S', ' '));
- EXPECT_FALSE(AtomMatchesChar(true, 'S', '\r'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 'S', '\0'));
- EXPECT_TRUE(AtomMatchesChar(true, 'S', 'a'));
- EXPECT_TRUE(AtomMatchesChar(true, 'S', '9'));
-}
-
-TEST(AtomMatchesCharTest, Escaped_w) {
- EXPECT_FALSE(AtomMatchesChar(true, 'w', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'w', '+'));
- EXPECT_FALSE(AtomMatchesChar(true, 'w', ' '));
- EXPECT_FALSE(AtomMatchesChar(true, 'w', '\n'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 'w', '0'));
- EXPECT_TRUE(AtomMatchesChar(true, 'w', 'b'));
- EXPECT_TRUE(AtomMatchesChar(true, 'w', 'C'));
- EXPECT_TRUE(AtomMatchesChar(true, 'w', '_'));
-}
-
-TEST(AtomMatchesCharTest, Escaped_W) {
- EXPECT_FALSE(AtomMatchesChar(true, 'W', 'A'));
- EXPECT_FALSE(AtomMatchesChar(true, 'W', 'b'));
- EXPECT_FALSE(AtomMatchesChar(true, 'W', '9'));
- EXPECT_FALSE(AtomMatchesChar(true, 'W', '_'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 'W', '\0'));
- EXPECT_TRUE(AtomMatchesChar(true, 'W', '*'));
- EXPECT_TRUE(AtomMatchesChar(true, 'W', '\n'));
-}
-
-TEST(AtomMatchesCharTest, EscapedWhiteSpace) {
- EXPECT_FALSE(AtomMatchesChar(true, 'f', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'f', '\n'));
- EXPECT_FALSE(AtomMatchesChar(true, 'n', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'n', '\r'));
- EXPECT_FALSE(AtomMatchesChar(true, 'r', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'r', 'a'));
- EXPECT_FALSE(AtomMatchesChar(true, 't', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 't', 't'));
- EXPECT_FALSE(AtomMatchesChar(true, 'v', '\0'));
- EXPECT_FALSE(AtomMatchesChar(true, 'v', '\f'));
-
- EXPECT_TRUE(AtomMatchesChar(true, 'f', '\f'));
- EXPECT_TRUE(AtomMatchesChar(true, 'n', '\n'));
- EXPECT_TRUE(AtomMatchesChar(true, 'r', '\r'));
- EXPECT_TRUE(AtomMatchesChar(true, 't', '\t'));
- EXPECT_TRUE(AtomMatchesChar(true, 'v', '\v'));
-}
-
-TEST(AtomMatchesCharTest, UnescapedDot) {
- EXPECT_FALSE(AtomMatchesChar(false, '.', '\n'));
-
- EXPECT_TRUE(AtomMatchesChar(false, '.', '\0'));
- EXPECT_TRUE(AtomMatchesChar(false, '.', '.'));
- EXPECT_TRUE(AtomMatchesChar(false, '.', 'a'));
- EXPECT_TRUE(AtomMatchesChar(false, '.', ' '));
-}
-
-TEST(AtomMatchesCharTest, UnescapedChar) {
- EXPECT_FALSE(AtomMatchesChar(false, 'a', '\0'));
- EXPECT_FALSE(AtomMatchesChar(false, 'a', 'b'));
- EXPECT_FALSE(AtomMatchesChar(false, '$', 'a'));
-
- EXPECT_TRUE(AtomMatchesChar(false, '$', '$'));
- EXPECT_TRUE(AtomMatchesChar(false, '5', '5'));
- EXPECT_TRUE(AtomMatchesChar(false, 'Z', 'Z'));
-}
-
-TEST(ValidateRegexTest, GeneratesFailureAndReturnsFalseForInvalid) {
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(NULL)),
- "NULL is not a valid simple regular expression");
- EXPECT_NONFATAL_FAILURE(
- ASSERT_FALSE(ValidateRegex("a\\")),
- "Syntax error at index 1 in simple regular expression \"a\\\": ");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a\\")),
- "'\\' cannot appear at the end");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\n\\")),
- "'\\' cannot appear at the end");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("\\s\\hb")),
- "invalid escape sequence \"\\h\"");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^^")),
- "'^' can only appear at the beginning");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex(".*^b")),
- "'^' can only appear at the beginning");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("$$")),
- "'$' can only appear at the end");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^$a")),
- "'$' can only appear at the end");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a(b")),
- "'(' is unsupported");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("ab)")),
- "')' is unsupported");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("[ab")),
- "'[' is unsupported");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("a{2")),
- "'{' is unsupported");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("?")),
- "'?' can only follow a repeatable token");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("^*")),
- "'*' can only follow a repeatable token");
- EXPECT_NONFATAL_FAILURE(ASSERT_FALSE(ValidateRegex("5*+")),
- "'+' can only follow a repeatable token");
-}
-
-TEST(ValidateRegexTest, ReturnsTrueForValid) {
- EXPECT_TRUE(ValidateRegex(""));
- EXPECT_TRUE(ValidateRegex("a"));
- EXPECT_TRUE(ValidateRegex(".*"));
- EXPECT_TRUE(ValidateRegex("^a_+"));
- EXPECT_TRUE(ValidateRegex("^a\\t\\&?"));
- EXPECT_TRUE(ValidateRegex("09*$"));
- EXPECT_TRUE(ValidateRegex("^Z$"));
- EXPECT_TRUE(ValidateRegex("a\\^Z\\$\\(\\)\\|\\[\\]\\{\\}"));
-}
-
-TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrOne) {
- EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "a", "ba"));
- // Repeating more than once.
- EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "aab"));
-
- // Repeating zero times.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ba"));
- // Repeating once.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, 'a', '?', "b", "ab"));
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '#', '?', ".", "##"));
-}
-
-TEST(MatchRepetitionAndRegexAtHeadTest, WorksForZeroOrMany) {
- EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '*', "a$", "baab"));
-
- // Repeating zero times.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "bc"));
- // Repeating once.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '*', "b", "abc"));
- // Repeating more than once.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '*', "-", "ab_1-g"));
-}
-
-TEST(MatchRepetitionAndRegexAtHeadTest, WorksForOneOrMany) {
- EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "a$", "baab"));
- // Repeating zero times.
- EXPECT_FALSE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "bc"));
-
- // Repeating once.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(false, '.', '+', "b", "abc"));
- // Repeating more than once.
- EXPECT_TRUE(MatchRepetitionAndRegexAtHead(true, 'w', '+', "-", "ab_1-g"));
-}
-
-TEST(MatchRegexAtHeadTest, ReturnsTrueForEmptyRegex) {
- EXPECT_TRUE(MatchRegexAtHead("", ""));
- EXPECT_TRUE(MatchRegexAtHead("", "ab"));
-}
-
-TEST(MatchRegexAtHeadTest, WorksWhenDollarIsInRegex) {
- EXPECT_FALSE(MatchRegexAtHead("$", "a"));
-
- EXPECT_TRUE(MatchRegexAtHead("$", ""));
- EXPECT_TRUE(MatchRegexAtHead("a$", "a"));
-}
-
-TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithEscapeSequence) {
- EXPECT_FALSE(MatchRegexAtHead("\\w", "+"));
- EXPECT_FALSE(MatchRegexAtHead("\\W", "ab"));
-
- EXPECT_TRUE(MatchRegexAtHead("\\sa", "\nab"));
- EXPECT_TRUE(MatchRegexAtHead("\\d", "1a"));
-}
-
-TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) {
- EXPECT_FALSE(MatchRegexAtHead(".+a", "abc"));
- EXPECT_FALSE(MatchRegexAtHead("a?b", "aab"));
-
- EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab"));
- EXPECT_TRUE(MatchRegexAtHead("a?b", "b"));
- EXPECT_TRUE(MatchRegexAtHead("a?b", "ab"));
-}
-
-TEST(MatchRegexAtHeadTest,
- WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
- EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc"));
- EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b"));
-
- EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab"));
- EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b"));
- EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b"));
- EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b"));
-}
-
-TEST(MatchRegexAtHeadTest, MatchesSequentially) {
- EXPECT_FALSE(MatchRegexAtHead("ab.*c", "acabc"));
-
- EXPECT_TRUE(MatchRegexAtHead("ab.*c", "ab-fsc"));
-}
-
-TEST(MatchRegexAnywhereTest, ReturnsFalseWhenStringIsNull) {
- EXPECT_FALSE(MatchRegexAnywhere("", NULL));
-}
-
-TEST(MatchRegexAnywhereTest, WorksWhenRegexStartsWithCaret) {
- EXPECT_FALSE(MatchRegexAnywhere("^a", "ba"));
- EXPECT_FALSE(MatchRegexAnywhere("^$", "a"));
-
- EXPECT_TRUE(MatchRegexAnywhere("^a", "ab"));
- EXPECT_TRUE(MatchRegexAnywhere("^", "ab"));
- EXPECT_TRUE(MatchRegexAnywhere("^$", ""));
-}
-
-TEST(MatchRegexAnywhereTest, ReturnsFalseWhenNoMatch) {
- EXPECT_FALSE(MatchRegexAnywhere("a", "bcde123"));
- EXPECT_FALSE(MatchRegexAnywhere("a.+a", "--aa88888888"));
-}
-
-TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingPrefix) {
- EXPECT_TRUE(MatchRegexAnywhere("\\w+", "ab1_ - 5"));
- EXPECT_TRUE(MatchRegexAnywhere(".*=", "="));
- EXPECT_TRUE(MatchRegexAnywhere("x.*ab?.*bc", "xaaabc"));
-}
-
-TEST(MatchRegexAnywhereTest, ReturnsTrueWhenMatchingNonPrefix) {
- EXPECT_TRUE(MatchRegexAnywhere("\\w+", "$$$ ab1_ - 5"));
- EXPECT_TRUE(MatchRegexAnywhere("\\.+=", "= ...="));
-}
-
-// Tests RE's implicit constructors.
-TEST(RETest, ImplicitConstructorWorks) {
- const RE empty("");
- EXPECT_STREQ("", empty.pattern());
-
- const RE simple("hello");
- EXPECT_STREQ("hello", simple.pattern());
-}
-
-// Tests that RE's constructors reject invalid regular expressions.
-TEST(RETest, RejectsInvalidRegex) {
- EXPECT_NONFATAL_FAILURE({
- const RE normal(NULL);
- }, "NULL is not a valid simple regular expression");
-
- EXPECT_NONFATAL_FAILURE({
- const RE normal(".*(\\w+");
- }, "'(' is unsupported");
-
- EXPECT_NONFATAL_FAILURE({
- const RE invalid("^?");
- }, "'?' can only follow a repeatable token");
-}
-
-// Tests RE::FullMatch().
-TEST(RETest, FullMatchWorks) {
- const RE empty("");
- EXPECT_TRUE(RE::FullMatch("", empty));
- EXPECT_FALSE(RE::FullMatch("a", empty));
-
- const RE re1("a");
- EXPECT_TRUE(RE::FullMatch("a", re1));
-
- const RE re("a.*z");
- EXPECT_TRUE(RE::FullMatch("az", re));
- EXPECT_TRUE(RE::FullMatch("axyz", re));
- EXPECT_FALSE(RE::FullMatch("baz", re));
- EXPECT_FALSE(RE::FullMatch("azy", re));
-}
-
-// Tests RE::PartialMatch().
-TEST(RETest, PartialMatchWorks) {
- const RE empty("");
- EXPECT_TRUE(RE::PartialMatch("", empty));
- EXPECT_TRUE(RE::PartialMatch("a", empty));
-
- const RE re("a.*z");
- EXPECT_TRUE(RE::PartialMatch("az", re));
- EXPECT_TRUE(RE::PartialMatch("axyz", re));
- EXPECT_TRUE(RE::PartialMatch("baz", re));
- EXPECT_TRUE(RE::PartialMatch("azy", re));
- EXPECT_FALSE(RE::PartialMatch("zza", re));
-}
-
-#endif // GTEST_USES_POSIX_RE
-
-#if !GTEST_OS_WINDOWS_MOBILE
-
-TEST(CaptureTest, CapturesStdout) {
- CaptureStdout();
- fprintf(stdout, "abc");
- EXPECT_STREQ("abc", GetCapturedStdout().c_str());
-
- CaptureStdout();
- fprintf(stdout, "def%cghi", '\0');
- EXPECT_EQ(::std::string("def\0ghi", 7), ::std::string(GetCapturedStdout()));
-}
-
-TEST(CaptureTest, CapturesStderr) {
- CaptureStderr();
- fprintf(stderr, "jkl");
- EXPECT_STREQ("jkl", GetCapturedStderr().c_str());
-
- CaptureStderr();
- fprintf(stderr, "jkl%cmno", '\0');
- EXPECT_EQ(::std::string("jkl\0mno", 7), ::std::string(GetCapturedStderr()));
-}
-
-// Tests that stdout and stderr capture don't interfere with each other.
-TEST(CaptureTest, CapturesStdoutAndStderr) {
- CaptureStdout();
- CaptureStderr();
- fprintf(stdout, "pqr");
- fprintf(stderr, "stu");
- EXPECT_STREQ("pqr", GetCapturedStdout().c_str());
- EXPECT_STREQ("stu", GetCapturedStderr().c_str());
-}
-
-TEST(CaptureDeathTest, CannotReenterStdoutCapture) {
- CaptureStdout();
- EXPECT_DEATH_IF_SUPPORTED(CaptureStdout(),
- "Only one stdout capturer can exist at a time");
- GetCapturedStdout();
-
- // We cannot test stderr capturing using death tests as they use it
- // themselves.
-}
-
-#endif // !GTEST_OS_WINDOWS_MOBILE
-
-TEST(ThreadLocalTest, DefaultConstructorInitializesToDefaultValues) {
- ThreadLocal<int> t1;
- EXPECT_EQ(0, t1.get());
-
- ThreadLocal<void*> t2;
- EXPECT_TRUE(t2.get() == nullptr);
-}
-
-TEST(ThreadLocalTest, SingleParamConstructorInitializesToParam) {
- ThreadLocal<int> t1(123);
- EXPECT_EQ(123, t1.get());
-
- int i = 0;
- ThreadLocal<int*> t2(&i);
- EXPECT_EQ(&i, t2.get());
-}
-
-class NoDefaultContructor {
- public:
- explicit NoDefaultContructor(const char*) {}
- NoDefaultContructor(const NoDefaultContructor&) {}
-};
-
-TEST(ThreadLocalTest, ValueDefaultContructorIsNotRequiredForParamVersion) {
- ThreadLocal<NoDefaultContructor> bar(NoDefaultContructor("foo"));
- bar.pointer();
-}
-
-TEST(ThreadLocalTest, GetAndPointerReturnSameValue) {
- ThreadLocal<std::string> thread_local_string;
-
- EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get()));
-
- // Verifies the condition still holds after calling set.
- thread_local_string.set("foo");
- EXPECT_EQ(thread_local_string.pointer(), &(thread_local_string.get()));
-}
-
-TEST(ThreadLocalTest, PointerAndConstPointerReturnSameValue) {
- ThreadLocal<std::string> thread_local_string;
- const ThreadLocal<std::string>& const_thread_local_string =
- thread_local_string;
-
- EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer());
-
- thread_local_string.set("foo");
- EXPECT_EQ(thread_local_string.pointer(), const_thread_local_string.pointer());
-}
-
-#if GTEST_IS_THREADSAFE
-
-void AddTwo(int* param) { *param += 2; }
-
-TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
- int i = 40;
- ThreadWithParam<int*> thread(&AddTwo, &i, nullptr);
- thread.Join();
- EXPECT_EQ(42, i);
-}
-
-TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
- // AssertHeld() is flaky only in the presence of multiple threads accessing
- // the lock. In this case, the test is robust.
- EXPECT_DEATH_IF_SUPPORTED({
- Mutex m;
- { MutexLock lock(&m); }
- m.AssertHeld();
- },
- "thread .*hold");
-}
-
-TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
- Mutex m;
- MutexLock lock(&m);
- m.AssertHeld();
-}
-
-class AtomicCounterWithMutex {
- public:
- explicit AtomicCounterWithMutex(Mutex* mutex) :
- value_(0), mutex_(mutex), random_(42) {}
-
- void Increment() {
- MutexLock lock(mutex_);
- int temp = value_;
- {
- // We need to put up a memory barrier to prevent reads and writes to
- // value_ rearranged with the call to SleepMilliseconds when observed
- // from other threads.
-#if GTEST_HAS_PTHREAD
- // On POSIX, locking a mutex puts up a memory barrier. We cannot use
- // Mutex and MutexLock here or rely on their memory barrier
- // functionality as we are testing them here.
- pthread_mutex_t memory_barrier_mutex;
- GTEST_CHECK_POSIX_SUCCESS_(
- pthread_mutex_init(&memory_barrier_mutex, nullptr));
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
-
- SleepMilliseconds(static_cast<int>(random_.Generate(30)));
-
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
- GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex));
-#elif GTEST_OS_WINDOWS
- // On Windows, performing an interlocked access puts up a memory barrier.
- volatile LONG dummy = 0;
- ::InterlockedIncrement(&dummy);
- SleepMilliseconds(static_cast<int>(random_.Generate(30)));
- ::InterlockedIncrement(&dummy);
-#else
-# error "Memory barrier not implemented on this platform."
-#endif // GTEST_HAS_PTHREAD
- }
- value_ = temp + 1;
- }
- int value() const { return value_; }
-
- private:
- volatile int value_;
- Mutex* const mutex_; // Protects value_.
- Random random_;
-};
-
-void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
- for (int i = 0; i < param.second; ++i)
- param.first->Increment();
-}
-
-// Tests that the mutex only lets one thread at a time to lock it.
-TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
- Mutex mutex;
- AtomicCounterWithMutex locked_counter(&mutex);
-
- typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
- const int kCycleCount = 20;
- const int kThreadCount = 7;
- std::unique_ptr<ThreadType> counting_threads[kThreadCount];
- Notification threads_can_start;
- // Creates and runs kThreadCount threads that increment locked_counter
- // kCycleCount times each.
- for (int i = 0; i < kThreadCount; ++i) {
- counting_threads[i].reset(new ThreadType(&CountingThreadFunc,
- make_pair(&locked_counter,
- kCycleCount),
- &threads_can_start));
- }
- threads_can_start.Notify();
- for (int i = 0; i < kThreadCount; ++i)
- counting_threads[i]->Join();
-
- // If the mutex lets more than one thread to increment the counter at a
- // time, they are likely to encounter a race condition and have some
- // increments overwritten, resulting in the lower then expected counter
- // value.
- EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
-}
-
-template <typename T>
-void RunFromThread(void (func)(T), T param) {
- ThreadWithParam<T> thread(func, param, nullptr);
- thread.Join();
-}
-
-void RetrieveThreadLocalValue(
- pair<ThreadLocal<std::string>*, std::string*> param) {
- *param.second = param.first->get();
-}
-
-TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
- ThreadLocal<std::string> thread_local_string("foo");
- EXPECT_STREQ("foo", thread_local_string.get().c_str());
-
- thread_local_string.set("bar");
- EXPECT_STREQ("bar", thread_local_string.get().c_str());
-
- std::string result;
- RunFromThread(&RetrieveThreadLocalValue,
- make_pair(&thread_local_string, &result));
- EXPECT_STREQ("foo", result.c_str());
-}
-
-// Keeps track of whether of destructors being called on instances of
-// DestructorTracker. On Windows, waits for the destructor call reports.
-class DestructorCall {
- public:
- DestructorCall() {
- invoked_ = false;
-#if GTEST_OS_WINDOWS
- wait_event_.Reset(::CreateEvent(NULL, TRUE, FALSE, NULL));
- GTEST_CHECK_(wait_event_.Get() != NULL);
-#endif
- }
-
- bool CheckDestroyed() const {
-#if GTEST_OS_WINDOWS
- if (::WaitForSingleObject(wait_event_.Get(), 1000) != WAIT_OBJECT_0)
- return false;
-#endif
- return invoked_;
- }
-
- void ReportDestroyed() {
- invoked_ = true;
-#if GTEST_OS_WINDOWS
- ::SetEvent(wait_event_.Get());
-#endif
- }
-
- static std::vector<DestructorCall*>& List() { return *list_; }
-
- static void ResetList() {
- for (size_t i = 0; i < list_->size(); ++i) {
- delete list_->at(i);
- }
- list_->clear();
- }
-
- private:
- bool invoked_;
-#if GTEST_OS_WINDOWS
- AutoHandle wait_event_;
-#endif
- static std::vector<DestructorCall*>* const list_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(DestructorCall);
-};
-
-std::vector<DestructorCall*>* const DestructorCall::list_ =
- new std::vector<DestructorCall*>;
-
-// DestructorTracker keeps track of whether its instances have been
-// destroyed.
-class DestructorTracker {
- public:
- DestructorTracker() : index_(GetNewIndex()) {}
- DestructorTracker(const DestructorTracker& /* rhs */)
- : index_(GetNewIndex()) {}
- ~DestructorTracker() {
- // We never access DestructorCall::List() concurrently, so we don't need
- // to protect this access with a mutex.
- DestructorCall::List()[index_]->ReportDestroyed();
- }
-
- private:
- static size_t GetNewIndex() {
- DestructorCall::List().push_back(new DestructorCall);
- return DestructorCall::List().size() - 1;
- }
- const size_t index_;
-
- GTEST_DISALLOW_ASSIGN_(DestructorTracker);
-};
-
-typedef ThreadLocal<DestructorTracker>* ThreadParam;
-
-void CallThreadLocalGet(ThreadParam thread_local_param) {
- thread_local_param->get();
-}
-
-// Tests that when a ThreadLocal object dies in a thread, it destroys
-// the managed object for that thread.
-TEST(ThreadLocalTest, DestroysManagedObjectForOwnThreadWhenDying) {
- DestructorCall::ResetList();
-
- {
- ThreadLocal<DestructorTracker> thread_local_tracker;
- ASSERT_EQ(0U, DestructorCall::List().size());
-
- // This creates another DestructorTracker object for the main thread.
- thread_local_tracker.get();
- ASSERT_EQ(1U, DestructorCall::List().size());
- ASSERT_FALSE(DestructorCall::List()[0]->CheckDestroyed());
- }
-
- // Now thread_local_tracker has died.
- ASSERT_EQ(1U, DestructorCall::List().size());
- EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed());
-
- DestructorCall::ResetList();
-}
-
-// Tests that when a thread exits, the thread-local object for that
-// thread is destroyed.
-TEST(ThreadLocalTest, DestroysManagedObjectAtThreadExit) {
- DestructorCall::ResetList();
-
- {
- ThreadLocal<DestructorTracker> thread_local_tracker;
- ASSERT_EQ(0U, DestructorCall::List().size());
-
- // This creates another DestructorTracker object in the new thread.
- ThreadWithParam<ThreadParam> thread(&CallThreadLocalGet,
- &thread_local_tracker, nullptr);
- thread.Join();
-
- // The thread has exited, and we should have a DestroyedTracker
- // instance created for it. But it may not have been destroyed yet.
- ASSERT_EQ(1U, DestructorCall::List().size());
- }
-
- // The thread has exited and thread_local_tracker has died.
- ASSERT_EQ(1U, DestructorCall::List().size());
- EXPECT_TRUE(DestructorCall::List()[0]->CheckDestroyed());
-
- DestructorCall::ResetList();
-}
-
-TEST(ThreadLocalTest, ThreadLocalMutationsAffectOnlyCurrentThread) {
- ThreadLocal<std::string> thread_local_string;
- thread_local_string.set("Foo");
- EXPECT_STREQ("Foo", thread_local_string.get().c_str());
-
- std::string result;
- RunFromThread(&RetrieveThreadLocalValue,
- make_pair(&thread_local_string, &result));
- EXPECT_TRUE(result.empty());
-}
-
-#endif // GTEST_IS_THREADSAFE
-
-#if GTEST_OS_WINDOWS
-TEST(WindowsTypesTest, HANDLEIsVoidStar) {
- StaticAssertTypeEq<HANDLE, void*>();
-}
-
-#if GTEST_OS_WINDOWS_MINGW && !defined(__MINGW64_VERSION_MAJOR)
-TEST(WindowsTypesTest, _CRITICAL_SECTIONIs_CRITICAL_SECTION) {
- StaticAssertTypeEq<CRITICAL_SECTION, _CRITICAL_SECTION>();
-}
-#else
-TEST(WindowsTypesTest, CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION) {
- StaticAssertTypeEq<CRITICAL_SECTION, _RTL_CRITICAL_SECTION>();
-}
-#endif
-
-#endif // GTEST_OS_WINDOWS
-
-} // namespace internal
-} // namespace testing
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Google Test - The Google C++ Testing and Mocking Framework
-//
-// This file tests the universal value printer.
-
-#include <ctype.h>
-#include <limits.h>
-#include <string.h>
-#include <algorithm>
-#include <deque>
-#include <forward_list>
-#include <list>
-#include <map>
-#include <set>
-#include <sstream>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-#include "gtest/gtest-printers.h"
-#include "gtest/gtest.h"
-
-// Some user-defined types for testing the universal value printer.
-
-// An anonymous enum type.
-enum AnonymousEnum {
- kAE1 = -1,
- kAE2 = 1
-};
-
-// An enum without a user-defined printer.
-enum EnumWithoutPrinter {
- kEWP1 = -2,
- kEWP2 = 42
-};
-
-// An enum with a << operator.
-enum EnumWithStreaming {
- kEWS1 = 10
-};
-
-std::ostream& operator<<(std::ostream& os, EnumWithStreaming e) {
- return os << (e == kEWS1 ? "kEWS1" : "invalid");
-}
-
-// An enum with a PrintTo() function.
-enum EnumWithPrintTo {
- kEWPT1 = 1
-};
-
-void PrintTo(EnumWithPrintTo e, std::ostream* os) {
- *os << (e == kEWPT1 ? "kEWPT1" : "invalid");
-}
-
-// A class implicitly convertible to BiggestInt.
-class BiggestIntConvertible {
- public:
- operator ::testing::internal::BiggestInt() const { return 42; }
-};
-
-// A user-defined unprintable class template in the global namespace.
-template <typename T>
-class UnprintableTemplateInGlobal {
- public:
- UnprintableTemplateInGlobal() : value_() {}
- private:
- T value_;
-};
-
-// A user-defined streamable type in the global namespace.
-class StreamableInGlobal {
- public:
- virtual ~StreamableInGlobal() {}
-};
-
-inline void operator<<(::std::ostream& os, const StreamableInGlobal& /* x */) {
- os << "StreamableInGlobal";
-}
-
-void operator<<(::std::ostream& os, const StreamableInGlobal* /* x */) {
- os << "StreamableInGlobal*";
-}
-
-namespace foo {
-
-// A user-defined unprintable type in a user namespace.
-class UnprintableInFoo {
- public:
- UnprintableInFoo() : z_(0) { memcpy(xy_, "\xEF\x12\x0\x0\x34\xAB\x0\x0", 8); }
- double z() const { return z_; }
- private:
- char xy_[8];
- double z_;
-};
-
-// A user-defined printable type in a user-chosen namespace.
-struct PrintableViaPrintTo {
- PrintableViaPrintTo() : value() {}
- int value;
-};
-
-void PrintTo(const PrintableViaPrintTo& x, ::std::ostream* os) {
- *os << "PrintableViaPrintTo: " << x.value;
-}
-
-// A type with a user-defined << for printing its pointer.
-struct PointerPrintable {
-};
-
-::std::ostream& operator<<(::std::ostream& os,
- const PointerPrintable* /* x */) {
- return os << "PointerPrintable*";
-}
-
-// A user-defined printable class template in a user-chosen namespace.
-template <typename T>
-class PrintableViaPrintToTemplate {
- public:
- explicit PrintableViaPrintToTemplate(const T& a_value) : value_(a_value) {}
-
- const T& value() const { return value_; }
- private:
- T value_;
-};
-
-template <typename T>
-void PrintTo(const PrintableViaPrintToTemplate<T>& x, ::std::ostream* os) {
- *os << "PrintableViaPrintToTemplate: " << x.value();
-}
-
-// A user-defined streamable class template in a user namespace.
-template <typename T>
-class StreamableTemplateInFoo {
- public:
- StreamableTemplateInFoo() : value_() {}
-
- const T& value() const { return value_; }
- private:
- T value_;
-};
-
-template <typename T>
-inline ::std::ostream& operator<<(::std::ostream& os,
- const StreamableTemplateInFoo<T>& x) {
- return os << "StreamableTemplateInFoo: " << x.value();
-}
-
-// A user-defined streamable but recursivly-defined container type in
-// a user namespace, it mimics therefore std::filesystem::path or
-// boost::filesystem::path.
-class PathLike {
- public:
- struct iterator {
- typedef PathLike value_type;
-
- iterator& operator++();
- PathLike& operator*();
- };
-
- using value_type = char;
- using const_iterator = iterator;
-
- PathLike() {}
-
- iterator begin() const { return iterator(); }
- iterator end() const { return iterator(); }
-
- friend ::std::ostream& operator<<(::std::ostream& os, const PathLike&) {
- return os << "Streamable-PathLike";
- }
-};
-
-} // namespace foo
-
-namespace testing {
-namespace gtest_printers_test {
-
-using ::std::deque;
-using ::std::list;
-using ::std::make_pair;
-using ::std::map;
-using ::std::multimap;
-using ::std::multiset;
-using ::std::pair;
-using ::std::set;
-using ::std::vector;
-using ::testing::PrintToString;
-using ::testing::internal::FormatForComparisonFailureMessage;
-using ::testing::internal::ImplicitCast_;
-using ::testing::internal::NativeArray;
-using ::testing::internal::RE;
-using ::testing::internal::RelationToSourceReference;
-using ::testing::internal::Strings;
-using ::testing::internal::UniversalPrint;
-using ::testing::internal::UniversalPrinter;
-using ::testing::internal::UniversalTersePrint;
-using ::testing::internal::UniversalTersePrintTupleFieldsToStrings;
-
-// Prints a value to a string using the universal value printer. This
-// is a helper for testing UniversalPrinter<T>::Print() for various types.
-template <typename T>
-std::string Print(const T& value) {
- ::std::stringstream ss;
- UniversalPrinter<T>::Print(value, &ss);
- return ss.str();
-}
-
-// Prints a value passed by reference to a string, using the universal
-// value printer. This is a helper for testing
-// UniversalPrinter<T&>::Print() for various types.
-template <typename T>
-std::string PrintByRef(const T& value) {
- ::std::stringstream ss;
- UniversalPrinter<T&>::Print(value, &ss);
- return ss.str();
-}
-
-// Tests printing various enum types.
-
-TEST(PrintEnumTest, AnonymousEnum) {
- EXPECT_EQ("-1", Print(kAE1));
- EXPECT_EQ("1", Print(kAE2));
-}
-
-TEST(PrintEnumTest, EnumWithoutPrinter) {
- EXPECT_EQ("-2", Print(kEWP1));
- EXPECT_EQ("42", Print(kEWP2));
-}
-
-TEST(PrintEnumTest, EnumWithStreaming) {
- EXPECT_EQ("kEWS1", Print(kEWS1));
- EXPECT_EQ("invalid", Print(static_cast<EnumWithStreaming>(0)));
-}
-
-TEST(PrintEnumTest, EnumWithPrintTo) {
- EXPECT_EQ("kEWPT1", Print(kEWPT1));
- EXPECT_EQ("invalid", Print(static_cast<EnumWithPrintTo>(0)));
-}
-
-// Tests printing a class implicitly convertible to BiggestInt.
-
-TEST(PrintClassTest, BiggestIntConvertible) {
- EXPECT_EQ("42", Print(BiggestIntConvertible()));
-}
-
-// Tests printing various char types.
-
-// char.
-TEST(PrintCharTest, PlainChar) {
- EXPECT_EQ("'\\0'", Print('\0'));
- EXPECT_EQ("'\\'' (39, 0x27)", Print('\''));
- EXPECT_EQ("'\"' (34, 0x22)", Print('"'));
- EXPECT_EQ("'?' (63, 0x3F)", Print('?'));
- EXPECT_EQ("'\\\\' (92, 0x5C)", Print('\\'));
- EXPECT_EQ("'\\a' (7)", Print('\a'));
- EXPECT_EQ("'\\b' (8)", Print('\b'));
- EXPECT_EQ("'\\f' (12, 0xC)", Print('\f'));
- EXPECT_EQ("'\\n' (10, 0xA)", Print('\n'));
- EXPECT_EQ("'\\r' (13, 0xD)", Print('\r'));
- EXPECT_EQ("'\\t' (9)", Print('\t'));
- EXPECT_EQ("'\\v' (11, 0xB)", Print('\v'));
- EXPECT_EQ("'\\x7F' (127)", Print('\x7F'));
- EXPECT_EQ("'\\xFF' (255)", Print('\xFF'));
- EXPECT_EQ("' ' (32, 0x20)", Print(' '));
- EXPECT_EQ("'a' (97, 0x61)", Print('a'));
-}
-
-// signed char.
-TEST(PrintCharTest, SignedChar) {
- EXPECT_EQ("'\\0'", Print(static_cast<signed char>('\0')));
- EXPECT_EQ("'\\xCE' (-50)",
- Print(static_cast<signed char>(-50)));
-}
-
-// unsigned char.
-TEST(PrintCharTest, UnsignedChar) {
- EXPECT_EQ("'\\0'", Print(static_cast<unsigned char>('\0')));
- EXPECT_EQ("'b' (98, 0x62)",
- Print(static_cast<unsigned char>('b')));
-}
-
-// Tests printing other simple, built-in types.
-
-// bool.
-TEST(PrintBuiltInTypeTest, Bool) {
- EXPECT_EQ("false", Print(false));
- EXPECT_EQ("true", Print(true));
-}
-
-// wchar_t.
-TEST(PrintBuiltInTypeTest, Wchar_t) {
- EXPECT_EQ("L'\\0'", Print(L'\0'));
- EXPECT_EQ("L'\\'' (39, 0x27)", Print(L'\''));
- EXPECT_EQ("L'\"' (34, 0x22)", Print(L'"'));
- EXPECT_EQ("L'?' (63, 0x3F)", Print(L'?'));
- EXPECT_EQ("L'\\\\' (92, 0x5C)", Print(L'\\'));
- EXPECT_EQ("L'\\a' (7)", Print(L'\a'));
- EXPECT_EQ("L'\\b' (8)", Print(L'\b'));
- EXPECT_EQ("L'\\f' (12, 0xC)", Print(L'\f'));
- EXPECT_EQ("L'\\n' (10, 0xA)", Print(L'\n'));
- EXPECT_EQ("L'\\r' (13, 0xD)", Print(L'\r'));
- EXPECT_EQ("L'\\t' (9)", Print(L'\t'));
- EXPECT_EQ("L'\\v' (11, 0xB)", Print(L'\v'));
- EXPECT_EQ("L'\\x7F' (127)", Print(L'\x7F'));
- EXPECT_EQ("L'\\xFF' (255)", Print(L'\xFF'));
- EXPECT_EQ("L' ' (32, 0x20)", Print(L' '));
- EXPECT_EQ("L'a' (97, 0x61)", Print(L'a'));
- EXPECT_EQ("L'\\x576' (1398)", Print(static_cast<wchar_t>(0x576)));
- EXPECT_EQ("L'\\xC74D' (51021)", Print(static_cast<wchar_t>(0xC74D)));
-}
-
-// Test that Int64 provides more storage than wchar_t.
-TEST(PrintTypeSizeTest, Wchar_t) {
- EXPECT_LT(sizeof(wchar_t), sizeof(testing::internal::Int64));
-}
-
-// Various integer types.
-TEST(PrintBuiltInTypeTest, Integer) {
- EXPECT_EQ("'\\xFF' (255)", Print(static_cast<unsigned char>(255))); // uint8
- EXPECT_EQ("'\\x80' (-128)", Print(static_cast<signed char>(-128))); // int8
- EXPECT_EQ("65535", Print(USHRT_MAX)); // uint16
- EXPECT_EQ("-32768", Print(SHRT_MIN)); // int16
- EXPECT_EQ("4294967295", Print(UINT_MAX)); // uint32
- EXPECT_EQ("-2147483648", Print(INT_MIN)); // int32
- EXPECT_EQ("18446744073709551615",
- Print(static_cast<testing::internal::UInt64>(-1))); // uint64
- EXPECT_EQ("-9223372036854775808",
- Print(static_cast<testing::internal::Int64>(1) << 63)); // int64
-}
-
-// Size types.
-TEST(PrintBuiltInTypeTest, Size_t) {
- EXPECT_EQ("1", Print(sizeof('a'))); // size_t.
-#if !GTEST_OS_WINDOWS
- // Windows has no ssize_t type.
- EXPECT_EQ("-2", Print(static_cast<ssize_t>(-2))); // ssize_t.
-#endif // !GTEST_OS_WINDOWS
-}
-
-// Floating-points.
-TEST(PrintBuiltInTypeTest, FloatingPoints) {
- EXPECT_EQ("1.5", Print(1.5f)); // float
- EXPECT_EQ("-2.5", Print(-2.5)); // double
-}
-
-// Since ::std::stringstream::operator<<(const void *) formats the pointer
-// output differently with different compilers, we have to create the expected
-// output first and use it as our expectation.
-static std::string PrintPointer(const void* p) {
- ::std::stringstream expected_result_stream;
- expected_result_stream << p;
- return expected_result_stream.str();
-}
-
-// Tests printing C strings.
-
-// const char*.
-TEST(PrintCStringTest, Const) {
- const char* p = "World";
- EXPECT_EQ(PrintPointer(p) + " pointing to \"World\"", Print(p));
-}
-
-// char*.
-TEST(PrintCStringTest, NonConst) {
- char p[] = "Hi";
- EXPECT_EQ(PrintPointer(p) + " pointing to \"Hi\"",
- Print(static_cast<char*>(p)));
-}
-
-// NULL C string.
-TEST(PrintCStringTest, Null) {
- const char* p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// Tests that C strings are escaped properly.
-TEST(PrintCStringTest, EscapesProperly) {
- const char* p = "'\"?\\\a\b\f\n\r\t\v\x7F\xFF a";
- EXPECT_EQ(PrintPointer(p) + " pointing to \"'\\\"?\\\\\\a\\b\\f"
- "\\n\\r\\t\\v\\x7F\\xFF a\"",
- Print(p));
-}
-
-// MSVC compiler can be configured to define whar_t as a typedef
-// of unsigned short. Defining an overload for const wchar_t* in that case
-// would cause pointers to unsigned shorts be printed as wide strings,
-// possibly accessing more memory than intended and causing invalid
-// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
-// wchar_t is implemented as a native type.
-#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
-
-// const wchar_t*.
-TEST(PrintWideCStringTest, Const) {
- const wchar_t* p = L"World";
- EXPECT_EQ(PrintPointer(p) + " pointing to L\"World\"", Print(p));
-}
-
-// wchar_t*.
-TEST(PrintWideCStringTest, NonConst) {
- wchar_t p[] = L"Hi";
- EXPECT_EQ(PrintPointer(p) + " pointing to L\"Hi\"",
- Print(static_cast<wchar_t*>(p)));
-}
-
-// NULL wide C string.
-TEST(PrintWideCStringTest, Null) {
- const wchar_t* p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// Tests that wide C strings are escaped properly.
-TEST(PrintWideCStringTest, EscapesProperly) {
- const wchar_t s[] = {'\'', '"', '?', '\\', '\a', '\b', '\f', '\n', '\r',
- '\t', '\v', 0xD3, 0x576, 0x8D3, 0xC74D, ' ', 'a', '\0'};
- EXPECT_EQ(PrintPointer(s) + " pointing to L\"'\\\"?\\\\\\a\\b\\f"
- "\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"",
- Print(static_cast<const wchar_t*>(s)));
-}
-#endif // native wchar_t
-
-// Tests printing pointers to other char types.
-
-// signed char*.
-TEST(PrintCharPointerTest, SignedChar) {
- signed char* p = reinterpret_cast<signed char*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const signed char*.
-TEST(PrintCharPointerTest, ConstSignedChar) {
- signed char* p = reinterpret_cast<signed char*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// unsigned char*.
-TEST(PrintCharPointerTest, UnsignedChar) {
- unsigned char* p = reinterpret_cast<unsigned char*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const unsigned char*.
-TEST(PrintCharPointerTest, ConstUnsignedChar) {
- const unsigned char* p = reinterpret_cast<const unsigned char*>(0x1234);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// Tests printing pointers to simple, built-in types.
-
-// bool*.
-TEST(PrintPointerToBuiltInTypeTest, Bool) {
- bool* p = reinterpret_cast<bool*>(0xABCD);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// void*.
-TEST(PrintPointerToBuiltInTypeTest, Void) {
- void* p = reinterpret_cast<void*>(0xABCD);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// const void*.
-TEST(PrintPointerToBuiltInTypeTest, ConstVoid) {
- const void* p = reinterpret_cast<const void*>(0xABCD);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// Tests printing pointers to pointers.
-TEST(PrintPointerToPointerTest, IntPointerPointer) {
- int** p = reinterpret_cast<int**>(0xABCD);
- EXPECT_EQ(PrintPointer(p), Print(p));
- p = nullptr;
- EXPECT_EQ("NULL", Print(p));
-}
-
-// Tests printing (non-member) function pointers.
-
-void MyFunction(int /* n */) {}
-
-TEST(PrintPointerTest, NonMemberFunctionPointer) {
- // We cannot directly cast &MyFunction to const void* because the
- // standard disallows casting between pointers to functions and
- // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
- // this limitation.
- EXPECT_EQ(
- PrintPointer(reinterpret_cast<const void*>(
- reinterpret_cast<internal::BiggestInt>(&MyFunction))),
- Print(&MyFunction));
- int (*p)(bool) = NULL; // NOLINT
- EXPECT_EQ("NULL", Print(p));
-}
-
-// An assertion predicate determining whether a one string is a prefix for
-// another.
-template <typename StringType>
-AssertionResult HasPrefix(const StringType& str, const StringType& prefix) {
- if (str.find(prefix, 0) == 0)
- return AssertionSuccess();
-
- const bool is_wide_string = sizeof(prefix[0]) > 1;
- const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
- return AssertionFailure()
- << begin_string_quote << prefix << "\" is not a prefix of "
- << begin_string_quote << str << "\"\n";
-}
-
-// Tests printing member variable pointers. Although they are called
-// pointers, they don't point to a location in the address space.
-// Their representation is implementation-defined. Thus they will be
-// printed as raw bytes.
-
-struct Foo {
- public:
- virtual ~Foo() {}
- int MyMethod(char x) { return x + 1; }
- virtual char MyVirtualMethod(int /* n */) { return 'a'; }
-
- int value;
-};
-
-TEST(PrintPointerTest, MemberVariablePointer) {
- EXPECT_TRUE(HasPrefix(Print(&Foo::value),
- Print(sizeof(&Foo::value)) + "-byte object "));
- int Foo::*p = NULL; // NOLINT
- EXPECT_TRUE(HasPrefix(Print(p),
- Print(sizeof(p)) + "-byte object "));
-}
-
-// Tests printing member function pointers. Although they are called
-// pointers, they don't point to a location in the address space.
-// Their representation is implementation-defined. Thus they will be
-// printed as raw bytes.
-TEST(PrintPointerTest, MemberFunctionPointer) {
- EXPECT_TRUE(HasPrefix(Print(&Foo::MyMethod),
- Print(sizeof(&Foo::MyMethod)) + "-byte object "));
- EXPECT_TRUE(
- HasPrefix(Print(&Foo::MyVirtualMethod),
- Print(sizeof((&Foo::MyVirtualMethod))) + "-byte object "));
- int (Foo::*p)(char) = NULL; // NOLINT
- EXPECT_TRUE(HasPrefix(Print(p),
- Print(sizeof(p)) + "-byte object "));
-}
-
-// Tests printing C arrays.
-
-// The difference between this and Print() is that it ensures that the
-// argument is a reference to an array.
-template <typename T, size_t N>
-std::string PrintArrayHelper(T (&a)[N]) {
- return Print(a);
-}
-
-// One-dimensional array.
-TEST(PrintArrayTest, OneDimensionalArray) {
- int a[5] = { 1, 2, 3, 4, 5 };
- EXPECT_EQ("{ 1, 2, 3, 4, 5 }", PrintArrayHelper(a));
-}
-
-// Two-dimensional array.
-TEST(PrintArrayTest, TwoDimensionalArray) {
- int a[2][5] = {
- { 1, 2, 3, 4, 5 },
- { 6, 7, 8, 9, 0 }
- };
- EXPECT_EQ("{ { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } }", PrintArrayHelper(a));
-}
-
-// Array of const elements.
-TEST(PrintArrayTest, ConstArray) {
- const bool a[1] = { false };
- EXPECT_EQ("{ false }", PrintArrayHelper(a));
-}
-
-// char array without terminating NUL.
-TEST(PrintArrayTest, CharArrayWithNoTerminatingNul) {
- // Array a contains '\0' in the middle and doesn't end with '\0'.
- char a[] = { 'H', '\0', 'i' };
- EXPECT_EQ("\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
-}
-
-// const char array with terminating NUL.
-TEST(PrintArrayTest, ConstCharArrayWithTerminatingNul) {
- const char a[] = "\0Hi";
- EXPECT_EQ("\"\\0Hi\"", PrintArrayHelper(a));
-}
-
-// const wchar_t array without terminating NUL.
-TEST(PrintArrayTest, WCharArrayWithNoTerminatingNul) {
- // Array a contains '\0' in the middle and doesn't end with '\0'.
- const wchar_t a[] = { L'H', L'\0', L'i' };
- EXPECT_EQ("L\"H\\0i\" (no terminating NUL)", PrintArrayHelper(a));
-}
-
-// wchar_t array with terminating NUL.
-TEST(PrintArrayTest, WConstCharArrayWithTerminatingNul) {
- const wchar_t a[] = L"\0Hi";
- EXPECT_EQ("L\"\\0Hi\"", PrintArrayHelper(a));
-}
-
-// Array of objects.
-TEST(PrintArrayTest, ObjectArray) {
- std::string a[3] = {"Hi", "Hello", "Ni hao"};
- EXPECT_EQ("{ \"Hi\", \"Hello\", \"Ni hao\" }", PrintArrayHelper(a));
-}
-
-// Array with many elements.
-TEST(PrintArrayTest, BigArray) {
- int a[100] = { 1, 2, 3 };
- EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0, 0, 0 }",
- PrintArrayHelper(a));
-}
-
-// Tests printing ::string and ::std::string.
-
-// ::std::string.
-TEST(PrintStringTest, StringInStdNamespace) {
- const char s[] = "'\"?\\\a\b\f\n\0\r\t\v\x7F\xFF a";
- const ::std::string str(s, sizeof(s));
- EXPECT_EQ("\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v\\x7F\\xFF a\\0\"",
- Print(str));
-}
-
-TEST(PrintStringTest, StringAmbiguousHex) {
- // "\x6BANANA" is ambiguous, it can be interpreted as starting with either of:
- // '\x6', '\x6B', or '\x6BA'.
-
- // a hex escaping sequence following by a decimal digit
- EXPECT_EQ("\"0\\x12\" \"3\"", Print(::std::string("0\x12" "3")));
- // a hex escaping sequence following by a hex digit (lower-case)
- EXPECT_EQ("\"mm\\x6\" \"bananas\"", Print(::std::string("mm\x6" "bananas")));
- // a hex escaping sequence following by a hex digit (upper-case)
- EXPECT_EQ("\"NOM\\x6\" \"BANANA\"", Print(::std::string("NOM\x6" "BANANA")));
- // a hex escaping sequence following by a non-xdigit
- EXPECT_EQ("\"!\\x5-!\"", Print(::std::string("!\x5-!")));
-}
-
-// Tests printing ::std::wstring.
-#if GTEST_HAS_STD_WSTRING
-// ::std::wstring.
-TEST(PrintWideStringTest, StringInStdNamespace) {
- const wchar_t s[] = L"'\"?\\\a\b\f\n\0\r\t\v\xD3\x576\x8D3\xC74D a";
- const ::std::wstring str(s, sizeof(s)/sizeof(wchar_t));
- EXPECT_EQ("L\"'\\\"?\\\\\\a\\b\\f\\n\\0\\r\\t\\v"
- "\\xD3\\x576\\x8D3\\xC74D a\\0\"",
- Print(str));
-}
-
-TEST(PrintWideStringTest, StringAmbiguousHex) {
- // same for wide strings.
- EXPECT_EQ("L\"0\\x12\" L\"3\"", Print(::std::wstring(L"0\x12" L"3")));
- EXPECT_EQ("L\"mm\\x6\" L\"bananas\"",
- Print(::std::wstring(L"mm\x6" L"bananas")));
- EXPECT_EQ("L\"NOM\\x6\" L\"BANANA\"",
- Print(::std::wstring(L"NOM\x6" L"BANANA")));
- EXPECT_EQ("L\"!\\x5-!\"", Print(::std::wstring(L"!\x5-!")));
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-// Tests printing types that support generic streaming (i.e. streaming
-// to std::basic_ostream<Char, CharTraits> for any valid Char and
-// CharTraits types).
-
-// Tests printing a non-template type that supports generic streaming.
-
-class AllowsGenericStreaming {};
-
-template <typename Char, typename CharTraits>
-std::basic_ostream<Char, CharTraits>& operator<<(
- std::basic_ostream<Char, CharTraits>& os,
- const AllowsGenericStreaming& /* a */) {
- return os << "AllowsGenericStreaming";
-}
-
-TEST(PrintTypeWithGenericStreamingTest, NonTemplateType) {
- AllowsGenericStreaming a;
- EXPECT_EQ("AllowsGenericStreaming", Print(a));
-}
-
-// Tests printing a template type that supports generic streaming.
-
-template <typename T>
-class AllowsGenericStreamingTemplate {};
-
-template <typename Char, typename CharTraits, typename T>
-std::basic_ostream<Char, CharTraits>& operator<<(
- std::basic_ostream<Char, CharTraits>& os,
- const AllowsGenericStreamingTemplate<T>& /* a */) {
- return os << "AllowsGenericStreamingTemplate";
-}
-
-TEST(PrintTypeWithGenericStreamingTest, TemplateType) {
- AllowsGenericStreamingTemplate<int> a;
- EXPECT_EQ("AllowsGenericStreamingTemplate", Print(a));
-}
-
-// Tests printing a type that supports generic streaming and can be
-// implicitly converted to another printable type.
-
-template <typename T>
-class AllowsGenericStreamingAndImplicitConversionTemplate {
- public:
- operator bool() const { return false; }
-};
-
-template <typename Char, typename CharTraits, typename T>
-std::basic_ostream<Char, CharTraits>& operator<<(
- std::basic_ostream<Char, CharTraits>& os,
- const AllowsGenericStreamingAndImplicitConversionTemplate<T>& /* a */) {
- return os << "AllowsGenericStreamingAndImplicitConversionTemplate";
-}
-
-TEST(PrintTypeWithGenericStreamingTest, TypeImplicitlyConvertible) {
- AllowsGenericStreamingAndImplicitConversionTemplate<int> a;
- EXPECT_EQ("AllowsGenericStreamingAndImplicitConversionTemplate", Print(a));
-}
-
-#if GTEST_HAS_ABSL
-
-// Tests printing ::absl::string_view.
-
-TEST(PrintStringViewTest, SimpleStringView) {
- const ::absl::string_view sp = "Hello";
- EXPECT_EQ("\"Hello\"", Print(sp));
-}
-
-TEST(PrintStringViewTest, UnprintableCharacters) {
- const char str[] = "NUL (\0) and \r\t";
- const ::absl::string_view sp(str, sizeof(str) - 1);
- EXPECT_EQ("\"NUL (\\0) and \\r\\t\"", Print(sp));
-}
-
-#endif // GTEST_HAS_ABSL
-
-// Tests printing STL containers.
-
-TEST(PrintStlContainerTest, EmptyDeque) {
- deque<char> empty;
- EXPECT_EQ("{}", Print(empty));
-}
-
-TEST(PrintStlContainerTest, NonEmptyDeque) {
- deque<int> non_empty;
- non_empty.push_back(1);
- non_empty.push_back(3);
- EXPECT_EQ("{ 1, 3 }", Print(non_empty));
-}
-
-
-TEST(PrintStlContainerTest, OneElementHashMap) {
- ::std::unordered_map<int, char> map1;
- map1[1] = 'a';
- EXPECT_EQ("{ (1, 'a' (97, 0x61)) }", Print(map1));
-}
-
-TEST(PrintStlContainerTest, HashMultiMap) {
- ::std::unordered_multimap<int, bool> map1;
- map1.insert(make_pair(5, true));
- map1.insert(make_pair(5, false));
-
- // Elements of hash_multimap can be printed in any order.
- const std::string result = Print(map1);
- EXPECT_TRUE(result == "{ (5, true), (5, false) }" ||
- result == "{ (5, false), (5, true) }")
- << " where Print(map1) returns \"" << result << "\".";
-}
-
-
-
-TEST(PrintStlContainerTest, HashSet) {
- ::std::unordered_set<int> set1;
- set1.insert(1);
- EXPECT_EQ("{ 1 }", Print(set1));
-}
-
-TEST(PrintStlContainerTest, HashMultiSet) {
- const int kSize = 5;
- int a[kSize] = { 1, 1, 2, 5, 1 };
- ::std::unordered_multiset<int> set1(a, a + kSize);
-
- // Elements of hash_multiset can be printed in any order.
- const std::string result = Print(set1);
- const std::string expected_pattern = "{ d, d, d, d, d }"; // d means a digit.
-
- // Verifies the result matches the expected pattern; also extracts
- // the numbers in the result.
- ASSERT_EQ(expected_pattern.length(), result.length());
- std::vector<int> numbers;
- for (size_t i = 0; i != result.length(); i++) {
- if (expected_pattern[i] == 'd') {
- ASSERT_NE(isdigit(static_cast<unsigned char>(result[i])), 0);
- numbers.push_back(result[i] - '0');
- } else {
- EXPECT_EQ(expected_pattern[i], result[i]) << " where result is "
- << result;
- }
- }
-
- // Makes sure the result contains the right numbers.
- std::sort(numbers.begin(), numbers.end());
- std::sort(a, a + kSize);
- EXPECT_TRUE(std::equal(a, a + kSize, numbers.begin()));
-}
-
-
-TEST(PrintStlContainerTest, List) {
- const std::string a[] = {"hello", "world"};
- const list<std::string> strings(a, a + 2);
- EXPECT_EQ("{ \"hello\", \"world\" }", Print(strings));
-}
-
-TEST(PrintStlContainerTest, Map) {
- map<int, bool> map1;
- map1[1] = true;
- map1[5] = false;
- map1[3] = true;
- EXPECT_EQ("{ (1, true), (3, true), (5, false) }", Print(map1));
-}
-
-TEST(PrintStlContainerTest, MultiMap) {
- multimap<bool, int> map1;
- // The make_pair template function would deduce the type as
- // pair<bool, int> here, and since the key part in a multimap has to
- // be constant, without a templated ctor in the pair class (as in
- // libCstd on Solaris), make_pair call would fail to compile as no
- // implicit conversion is found. Thus explicit typename is used
- // here instead.
- map1.insert(pair<const bool, int>(true, 0));
- map1.insert(pair<const bool, int>(true, 1));
- map1.insert(pair<const bool, int>(false, 2));
- EXPECT_EQ("{ (false, 2), (true, 0), (true, 1) }", Print(map1));
-}
-
-TEST(PrintStlContainerTest, Set) {
- const unsigned int a[] = { 3, 0, 5 };
- set<unsigned int> set1(a, a + 3);
- EXPECT_EQ("{ 0, 3, 5 }", Print(set1));
-}
-
-TEST(PrintStlContainerTest, MultiSet) {
- const int a[] = { 1, 1, 2, 5, 1 };
- multiset<int> set1(a, a + 5);
- EXPECT_EQ("{ 1, 1, 1, 2, 5 }", Print(set1));
-}
-
-
-TEST(PrintStlContainerTest, SinglyLinkedList) {
- int a[] = { 9, 2, 8 };
- const std::forward_list<int> ints(a, a + 3);
- EXPECT_EQ("{ 9, 2, 8 }", Print(ints));
-}
-
-TEST(PrintStlContainerTest, Pair) {
- pair<const bool, int> p(true, 5);
- EXPECT_EQ("(true, 5)", Print(p));
-}
-
-TEST(PrintStlContainerTest, Vector) {
- vector<int> v;
- v.push_back(1);
- v.push_back(2);
- EXPECT_EQ("{ 1, 2 }", Print(v));
-}
-
-TEST(PrintStlContainerTest, LongSequence) {
- const int a[100] = { 1, 2, 3 };
- const vector<int> v(a, a + 100);
- EXPECT_EQ("{ 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "
- "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ... }", Print(v));
-}
-
-TEST(PrintStlContainerTest, NestedContainer) {
- const int a1[] = { 1, 2 };
- const int a2[] = { 3, 4, 5 };
- const list<int> l1(a1, a1 + 2);
- const list<int> l2(a2, a2 + 3);
-
- vector<list<int> > v;
- v.push_back(l1);
- v.push_back(l2);
- EXPECT_EQ("{ { 1, 2 }, { 3, 4, 5 } }", Print(v));
-}
-
-TEST(PrintStlContainerTest, OneDimensionalNativeArray) {
- const int a[3] = { 1, 2, 3 };
- NativeArray<int> b(a, 3, RelationToSourceReference());
- EXPECT_EQ("{ 1, 2, 3 }", Print(b));
-}
-
-TEST(PrintStlContainerTest, TwoDimensionalNativeArray) {
- const int a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
- NativeArray<int[3]> b(a, 2, RelationToSourceReference());
- EXPECT_EQ("{ { 1, 2, 3 }, { 4, 5, 6 } }", Print(b));
-}
-
-// Tests that a class named iterator isn't treated as a container.
-
-struct iterator {
- char x;
-};
-
-TEST(PrintStlContainerTest, Iterator) {
- iterator it = {};
- EXPECT_EQ("1-byte object <00>", Print(it));
-}
-
-// Tests that a class named const_iterator isn't treated as a container.
-
-struct const_iterator {
- char x;
-};
-
-TEST(PrintStlContainerTest, ConstIterator) {
- const_iterator it = {};
- EXPECT_EQ("1-byte object <00>", Print(it));
-}
-
-// Tests printing ::std::tuples.
-
-// Tuples of various arities.
-TEST(PrintStdTupleTest, VariousSizes) {
- ::std::tuple<> t0;
- EXPECT_EQ("()", Print(t0));
-
- ::std::tuple<int> t1(5);
- EXPECT_EQ("(5)", Print(t1));
-
- ::std::tuple<char, bool> t2('a', true);
- EXPECT_EQ("('a' (97, 0x61), true)", Print(t2));
-
- ::std::tuple<bool, int, int> t3(false, 2, 3);
- EXPECT_EQ("(false, 2, 3)", Print(t3));
-
- ::std::tuple<bool, int, int, int> t4(false, 2, 3, 4);
- EXPECT_EQ("(false, 2, 3, 4)", Print(t4));
-
- const char* const str = "8";
- ::std::tuple<bool, char, short, testing::internal::Int32, // NOLINT
- testing::internal::Int64, float, double, const char*, void*,
- std::string>
- t10(false, 'a', static_cast<short>(3), 4, 5, 1.5F, -2.5, str, // NOLINT
- nullptr, "10");
- EXPECT_EQ("(false, 'a' (97, 0x61), 3, 4, 5, 1.5, -2.5, " + PrintPointer(str) +
- " pointing to \"8\", NULL, \"10\")",
- Print(t10));
-}
-
-// Nested tuples.
-TEST(PrintStdTupleTest, NestedTuple) {
- ::std::tuple< ::std::tuple<int, bool>, char> nested(
- ::std::make_tuple(5, true), 'a');
- EXPECT_EQ("((5, true), 'a' (97, 0x61))", Print(nested));
-}
-
-TEST(PrintNullptrT, Basic) {
- EXPECT_EQ("(nullptr)", Print(nullptr));
-}
-
-TEST(PrintReferenceWrapper, Printable) {
- int x = 5;
- EXPECT_EQ("@" + PrintPointer(&x) + " 5", Print(std::ref(x)));
- EXPECT_EQ("@" + PrintPointer(&x) + " 5", Print(std::cref(x)));
-}
-
-TEST(PrintReferenceWrapper, Unprintable) {
- ::foo::UnprintableInFoo up;
- EXPECT_EQ(
- "@" + PrintPointer(&up) +
- " 16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
- Print(std::ref(up)));
- EXPECT_EQ(
- "@" + PrintPointer(&up) +
- " 16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
- Print(std::cref(up)));
-}
-
-// Tests printing user-defined unprintable types.
-
-// Unprintable types in the global namespace.
-TEST(PrintUnprintableTypeTest, InGlobalNamespace) {
- EXPECT_EQ("1-byte object <00>",
- Print(UnprintableTemplateInGlobal<char>()));
-}
-
-// Unprintable types in a user namespace.
-TEST(PrintUnprintableTypeTest, InUserNamespace) {
- EXPECT_EQ("16-byte object <EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
- Print(::foo::UnprintableInFoo()));
-}
-
-// Unprintable types are that too big to be printed completely.
-
-struct Big {
- Big() { memset(array, 0, sizeof(array)); }
- char array[257];
-};
-
-TEST(PrintUnpritableTypeTest, BigObject) {
- EXPECT_EQ("257-byte object <00-00 00-00 00-00 00-00 00-00 00-00 "
- "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
- "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
- "00-00 00-00 00-00 00-00 00-00 00-00 ... 00-00 00-00 00-00 "
- "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
- "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 "
- "00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00>",
- Print(Big()));
-}
-
-// Tests printing user-defined streamable types.
-
-// Streamable types in the global namespace.
-TEST(PrintStreamableTypeTest, InGlobalNamespace) {
- StreamableInGlobal x;
- EXPECT_EQ("StreamableInGlobal", Print(x));
- EXPECT_EQ("StreamableInGlobal*", Print(&x));
-}
-
-// Printable template types in a user namespace.
-TEST(PrintStreamableTypeTest, TemplateTypeInUserNamespace) {
- EXPECT_EQ("StreamableTemplateInFoo: 0",
- Print(::foo::StreamableTemplateInFoo<int>()));
-}
-
-// Tests printing a user-defined recursive container type that has a <<
-// operator.
-TEST(PrintStreamableTypeTest, PathLikeInUserNamespace) {
- ::foo::PathLike x;
- EXPECT_EQ("Streamable-PathLike", Print(x));
- const ::foo::PathLike cx;
- EXPECT_EQ("Streamable-PathLike", Print(cx));
-}
-
-// Tests printing user-defined types that have a PrintTo() function.
-TEST(PrintPrintableTypeTest, InUserNamespace) {
- EXPECT_EQ("PrintableViaPrintTo: 0",
- Print(::foo::PrintableViaPrintTo()));
-}
-
-// Tests printing a pointer to a user-defined type that has a <<
-// operator for its pointer.
-TEST(PrintPrintableTypeTest, PointerInUserNamespace) {
- ::foo::PointerPrintable x;
- EXPECT_EQ("PointerPrintable*", Print(&x));
-}
-
-// Tests printing user-defined class template that have a PrintTo() function.
-TEST(PrintPrintableTypeTest, TemplateInUserNamespace) {
- EXPECT_EQ("PrintableViaPrintToTemplate: 5",
- Print(::foo::PrintableViaPrintToTemplate<int>(5)));
-}
-
-// Tests that the universal printer prints both the address and the
-// value of a reference.
-TEST(PrintReferenceTest, PrintsAddressAndValue) {
- int n = 5;
- EXPECT_EQ("@" + PrintPointer(&n) + " 5", PrintByRef(n));
-
- int a[2][3] = {
- { 0, 1, 2 },
- { 3, 4, 5 }
- };
- EXPECT_EQ("@" + PrintPointer(a) + " { { 0, 1, 2 }, { 3, 4, 5 } }",
- PrintByRef(a));
-
- const ::foo::UnprintableInFoo x;
- EXPECT_EQ("@" + PrintPointer(&x) + " 16-byte object "
- "<EF-12 00-00 34-AB 00-00 00-00 00-00 00-00 00-00>",
- PrintByRef(x));
-}
-
-// Tests that the universal printer prints a function pointer passed by
-// reference.
-TEST(PrintReferenceTest, HandlesFunctionPointer) {
- void (*fp)(int n) = &MyFunction;
- const std::string fp_pointer_string =
- PrintPointer(reinterpret_cast<const void*>(&fp));
- // We cannot directly cast &MyFunction to const void* because the
- // standard disallows casting between pointers to functions and
- // pointers to objects, and some compilers (e.g. GCC 3.4) enforce
- // this limitation.
- const std::string fp_string = PrintPointer(reinterpret_cast<const void*>(
- reinterpret_cast<internal::BiggestInt>(fp)));
- EXPECT_EQ("@" + fp_pointer_string + " " + fp_string,
- PrintByRef(fp));
-}
-
-// Tests that the universal printer prints a member function pointer
-// passed by reference.
-TEST(PrintReferenceTest, HandlesMemberFunctionPointer) {
- int (Foo::*p)(char ch) = &Foo::MyMethod;
- EXPECT_TRUE(HasPrefix(
- PrintByRef(p),
- "@" + PrintPointer(reinterpret_cast<const void*>(&p)) + " " +
- Print(sizeof(p)) + "-byte object "));
-
- char (Foo::*p2)(int n) = &Foo::MyVirtualMethod;
- EXPECT_TRUE(HasPrefix(
- PrintByRef(p2),
- "@" + PrintPointer(reinterpret_cast<const void*>(&p2)) + " " +
- Print(sizeof(p2)) + "-byte object "));
-}
-
-// Tests that the universal printer prints a member variable pointer
-// passed by reference.
-TEST(PrintReferenceTest, HandlesMemberVariablePointer) {
- int Foo::*p = &Foo::value; // NOLINT
- EXPECT_TRUE(HasPrefix(
- PrintByRef(p),
- "@" + PrintPointer(&p) + " " + Print(sizeof(p)) + "-byte object "));
-}
-
-// Tests that FormatForComparisonFailureMessage(), which is used to print
-// an operand in a comparison assertion (e.g. ASSERT_EQ) when the assertion
-// fails, formats the operand in the desired way.
-
-// scalar
-TEST(FormatForComparisonFailureMessageTest, WorksForScalar) {
- EXPECT_STREQ("123",
- FormatForComparisonFailureMessage(123, 124).c_str());
-}
-
-// non-char pointer
-TEST(FormatForComparisonFailureMessageTest, WorksForNonCharPointer) {
- int n = 0;
- EXPECT_EQ(PrintPointer(&n),
- FormatForComparisonFailureMessage(&n, &n).c_str());
-}
-
-// non-char array
-TEST(FormatForComparisonFailureMessageTest, FormatsNonCharArrayAsPointer) {
- // In expression 'array == x', 'array' is compared by pointer.
- // Therefore we want to print an array operand as a pointer.
- int n[] = { 1, 2, 3 };
- EXPECT_EQ(PrintPointer(n),
- FormatForComparisonFailureMessage(n, n).c_str());
-}
-
-// Tests formatting a char pointer when it's compared with another pointer.
-// In this case we want to print it as a raw pointer, as the comparison is by
-// pointer.
-
-// char pointer vs pointer
-TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsPointer) {
- // In expression 'p == x', where 'p' and 'x' are (const or not) char
- // pointers, the operands are compared by pointer. Therefore we
- // want to print 'p' as a pointer instead of a C string (we don't
- // even know if it's supposed to point to a valid C string).
-
- // const char*
- const char* s = "hello";
- EXPECT_EQ(PrintPointer(s),
- FormatForComparisonFailureMessage(s, s).c_str());
-
- // char*
- char ch = 'a';
- EXPECT_EQ(PrintPointer(&ch),
- FormatForComparisonFailureMessage(&ch, &ch).c_str());
-}
-
-// wchar_t pointer vs pointer
-TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsPointer) {
- // In expression 'p == x', where 'p' and 'x' are (const or not) char
- // pointers, the operands are compared by pointer. Therefore we
- // want to print 'p' as a pointer instead of a wide C string (we don't
- // even know if it's supposed to point to a valid wide C string).
-
- // const wchar_t*
- const wchar_t* s = L"hello";
- EXPECT_EQ(PrintPointer(s),
- FormatForComparisonFailureMessage(s, s).c_str());
-
- // wchar_t*
- wchar_t ch = L'a';
- EXPECT_EQ(PrintPointer(&ch),
- FormatForComparisonFailureMessage(&ch, &ch).c_str());
-}
-
-// Tests formatting a char pointer when it's compared to a string object.
-// In this case we want to print the char pointer as a C string.
-
-// char pointer vs std::string
-TEST(FormatForComparisonFailureMessageTest, WorksForCharPointerVsStdString) {
- const char* s = "hello \"world";
- EXPECT_STREQ("\"hello \\\"world\"", // The string content should be escaped.
- FormatForComparisonFailureMessage(s, ::std::string()).c_str());
-
- // char*
- char str[] = "hi\1";
- char* p = str;
- EXPECT_STREQ("\"hi\\x1\"", // The string content should be escaped.
- FormatForComparisonFailureMessage(p, ::std::string()).c_str());
-}
-
-#if GTEST_HAS_STD_WSTRING
-// wchar_t pointer vs std::wstring
-TEST(FormatForComparisonFailureMessageTest, WorksForWCharPointerVsStdWString) {
- const wchar_t* s = L"hi \"world";
- EXPECT_STREQ("L\"hi \\\"world\"", // The string content should be escaped.
- FormatForComparisonFailureMessage(s, ::std::wstring()).c_str());
-
- // wchar_t*
- wchar_t str[] = L"hi\1";
- wchar_t* p = str;
- EXPECT_STREQ("L\"hi\\x1\"", // The string content should be escaped.
- FormatForComparisonFailureMessage(p, ::std::wstring()).c_str());
-}
-#endif
-
-// Tests formatting a char array when it's compared with a pointer or array.
-// In this case we want to print the array as a row pointer, as the comparison
-// is by pointer.
-
-// char array vs pointer
-TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsPointer) {
- char str[] = "hi \"world\"";
- char* p = nullptr;
- EXPECT_EQ(PrintPointer(str),
- FormatForComparisonFailureMessage(str, p).c_str());
-}
-
-// char array vs char array
-TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsCharArray) {
- const char str[] = "hi \"world\"";
- EXPECT_EQ(PrintPointer(str),
- FormatForComparisonFailureMessage(str, str).c_str());
-}
-
-// wchar_t array vs pointer
-TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsPointer) {
- wchar_t str[] = L"hi \"world\"";
- wchar_t* p = nullptr;
- EXPECT_EQ(PrintPointer(str),
- FormatForComparisonFailureMessage(str, p).c_str());
-}
-
-// wchar_t array vs wchar_t array
-TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsWCharArray) {
- const wchar_t str[] = L"hi \"world\"";
- EXPECT_EQ(PrintPointer(str),
- FormatForComparisonFailureMessage(str, str).c_str());
-}
-
-// Tests formatting a char array when it's compared with a string object.
-// In this case we want to print the array as a C string.
-
-// char array vs std::string
-TEST(FormatForComparisonFailureMessageTest, WorksForCharArrayVsStdString) {
- const char str[] = "hi \"world\"";
- EXPECT_STREQ("\"hi \\\"world\\\"\"", // The content should be escaped.
- FormatForComparisonFailureMessage(str, ::std::string()).c_str());
-}
-
-#if GTEST_HAS_STD_WSTRING
-// wchar_t array vs std::wstring
-TEST(FormatForComparisonFailureMessageTest, WorksForWCharArrayVsStdWString) {
- const wchar_t str[] = L"hi \"w\0rld\"";
- EXPECT_STREQ(
- "L\"hi \\\"w\"", // The content should be escaped.
- // Embedded NUL terminates the string.
- FormatForComparisonFailureMessage(str, ::std::wstring()).c_str());
-}
-#endif
-
-// Useful for testing PrintToString(). We cannot use EXPECT_EQ()
-// there as its implementation uses PrintToString(). The caller must
-// ensure that 'value' has no side effect.
-#define EXPECT_PRINT_TO_STRING_(value, expected_string) \
- EXPECT_TRUE(PrintToString(value) == (expected_string)) \
- << " where " #value " prints as " << (PrintToString(value))
-
-TEST(PrintToStringTest, WorksForScalar) {
- EXPECT_PRINT_TO_STRING_(123, "123");
-}
-
-TEST(PrintToStringTest, WorksForPointerToConstChar) {
- const char* p = "hello";
- EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
-}
-
-TEST(PrintToStringTest, WorksForPointerToNonConstChar) {
- char s[] = "hello";
- char* p = s;
- EXPECT_PRINT_TO_STRING_(p, "\"hello\"");
-}
-
-TEST(PrintToStringTest, EscapesForPointerToConstChar) {
- const char* p = "hello\n";
- EXPECT_PRINT_TO_STRING_(p, "\"hello\\n\"");
-}
-
-TEST(PrintToStringTest, EscapesForPointerToNonConstChar) {
- char s[] = "hello\1";
- char* p = s;
- EXPECT_PRINT_TO_STRING_(p, "\"hello\\x1\"");
-}
-
-TEST(PrintToStringTest, WorksForArray) {
- int n[3] = { 1, 2, 3 };
- EXPECT_PRINT_TO_STRING_(n, "{ 1, 2, 3 }");
-}
-
-TEST(PrintToStringTest, WorksForCharArray) {
- char s[] = "hello";
- EXPECT_PRINT_TO_STRING_(s, "\"hello\"");
-}
-
-TEST(PrintToStringTest, WorksForCharArrayWithEmbeddedNul) {
- const char str_with_nul[] = "hello\0 world";
- EXPECT_PRINT_TO_STRING_(str_with_nul, "\"hello\\0 world\"");
-
- char mutable_str_with_nul[] = "hello\0 world";
- EXPECT_PRINT_TO_STRING_(mutable_str_with_nul, "\"hello\\0 world\"");
-}
-
- TEST(PrintToStringTest, ContainsNonLatin) {
- // Sanity test with valid UTF-8. Prints both in hex and as text.
- std::string non_ascii_str = ::std::string("오전 4:30");
- EXPECT_PRINT_TO_STRING_(non_ascii_str,
- "\"\\xEC\\x98\\xA4\\xEC\\xA0\\x84 4:30\"\n"
- " As Text: \"오전 4:30\"");
- non_ascii_str = ::std::string("From ä — ẑ");
- EXPECT_PRINT_TO_STRING_(non_ascii_str,
- "\"From \\xC3\\xA4 \\xE2\\x80\\x94 \\xE1\\xBA\\x91\""
- "\n As Text: \"From ä — ẑ\"");
-}
-
-TEST(IsValidUTF8Test, IllFormedUTF8) {
- // The following test strings are ill-formed UTF-8 and are printed
- // as hex only (or ASCII, in case of ASCII bytes) because IsValidUTF8() is
- // expected to fail, thus output does not contain "As Text:".
-
- static const char *const kTestdata[][2] = {
- // 2-byte lead byte followed by a single-byte character.
- {"\xC3\x74", "\"\\xC3t\""},
- // Valid 2-byte character followed by an orphan trail byte.
- {"\xC3\x84\xA4", "\"\\xC3\\x84\\xA4\""},
- // Lead byte without trail byte.
- {"abc\xC3", "\"abc\\xC3\""},
- // 3-byte lead byte, single-byte character, orphan trail byte.
- {"x\xE2\x70\x94", "\"x\\xE2p\\x94\""},
- // Truncated 3-byte character.
- {"\xE2\x80", "\"\\xE2\\x80\""},
- // Truncated 3-byte character followed by valid 2-byte char.
- {"\xE2\x80\xC3\x84", "\"\\xE2\\x80\\xC3\\x84\""},
- // Truncated 3-byte character followed by a single-byte character.
- {"\xE2\x80\x7A", "\"\\xE2\\x80z\""},
- // 3-byte lead byte followed by valid 3-byte character.
- {"\xE2\xE2\x80\x94", "\"\\xE2\\xE2\\x80\\x94\""},
- // 4-byte lead byte followed by valid 3-byte character.
- {"\xF0\xE2\x80\x94", "\"\\xF0\\xE2\\x80\\x94\""},
- // Truncated 4-byte character.
- {"\xF0\xE2\x80", "\"\\xF0\\xE2\\x80\""},
- // Invalid UTF-8 byte sequences embedded in other chars.
- {"abc\xE2\x80\x94\xC3\x74xyc", "\"abc\\xE2\\x80\\x94\\xC3txyc\""},
- {"abc\xC3\x84\xE2\x80\xC3\x84xyz",
- "\"abc\\xC3\\x84\\xE2\\x80\\xC3\\x84xyz\""},
- // Non-shortest UTF-8 byte sequences are also ill-formed.
- // The classics: xC0, xC1 lead byte.
- {"\xC0\x80", "\"\\xC0\\x80\""},
- {"\xC1\x81", "\"\\xC1\\x81\""},
- // Non-shortest sequences.
- {"\xE0\x80\x80", "\"\\xE0\\x80\\x80\""},
- {"\xf0\x80\x80\x80", "\"\\xF0\\x80\\x80\\x80\""},
- // Last valid code point before surrogate range, should be printed as text,
- // too.
- {"\xED\x9F\xBF", "\"\\xED\\x9F\\xBF\"\n As Text: \"\""},
- // Start of surrogate lead. Surrogates are not printed as text.
- {"\xED\xA0\x80", "\"\\xED\\xA0\\x80\""},
- // Last non-private surrogate lead.
- {"\xED\xAD\xBF", "\"\\xED\\xAD\\xBF\""},
- // First private-use surrogate lead.
- {"\xED\xAE\x80", "\"\\xED\\xAE\\x80\""},
- // Last private-use surrogate lead.
- {"\xED\xAF\xBF", "\"\\xED\\xAF\\xBF\""},
- // Mid-point of surrogate trail.
- {"\xED\xB3\xBF", "\"\\xED\\xB3\\xBF\""},
- // First valid code point after surrogate range, should be printed as text,
- // too.
- {"\xEE\x80\x80", "\"\\xEE\\x80\\x80\"\n As Text: \"\""}
- };
-
- for (int i = 0; i < int(sizeof(kTestdata)/sizeof(kTestdata[0])); ++i) {
- EXPECT_PRINT_TO_STRING_(kTestdata[i][0], kTestdata[i][1]);
- }
-}
-
-#undef EXPECT_PRINT_TO_STRING_
-
-TEST(UniversalTersePrintTest, WorksForNonReference) {
- ::std::stringstream ss;
- UniversalTersePrint(123, &ss);
- EXPECT_EQ("123", ss.str());
-}
-
-TEST(UniversalTersePrintTest, WorksForReference) {
- const int& n = 123;
- ::std::stringstream ss;
- UniversalTersePrint(n, &ss);
- EXPECT_EQ("123", ss.str());
-}
-
-TEST(UniversalTersePrintTest, WorksForCString) {
- const char* s1 = "abc";
- ::std::stringstream ss1;
- UniversalTersePrint(s1, &ss1);
- EXPECT_EQ("\"abc\"", ss1.str());
-
- char* s2 = const_cast<char*>(s1);
- ::std::stringstream ss2;
- UniversalTersePrint(s2, &ss2);
- EXPECT_EQ("\"abc\"", ss2.str());
-
- const char* s3 = nullptr;
- ::std::stringstream ss3;
- UniversalTersePrint(s3, &ss3);
- EXPECT_EQ("NULL", ss3.str());
-}
-
-TEST(UniversalPrintTest, WorksForNonReference) {
- ::std::stringstream ss;
- UniversalPrint(123, &ss);
- EXPECT_EQ("123", ss.str());
-}
-
-TEST(UniversalPrintTest, WorksForReference) {
- const int& n = 123;
- ::std::stringstream ss;
- UniversalPrint(n, &ss);
- EXPECT_EQ("123", ss.str());
-}
-
-TEST(UniversalPrintTest, WorksForCString) {
- const char* s1 = "abc";
- ::std::stringstream ss1;
- UniversalPrint(s1, &ss1);
- EXPECT_EQ(PrintPointer(s1) + " pointing to \"abc\"", std::string(ss1.str()));
-
- char* s2 = const_cast<char*>(s1);
- ::std::stringstream ss2;
- UniversalPrint(s2, &ss2);
- EXPECT_EQ(PrintPointer(s2) + " pointing to \"abc\"", std::string(ss2.str()));
-
- const char* s3 = nullptr;
- ::std::stringstream ss3;
- UniversalPrint(s3, &ss3);
- EXPECT_EQ("NULL", ss3.str());
-}
-
-TEST(UniversalPrintTest, WorksForCharArray) {
- const char str[] = "\"Line\0 1\"\nLine 2";
- ::std::stringstream ss1;
- UniversalPrint(str, &ss1);
- EXPECT_EQ("\"\\\"Line\\0 1\\\"\\nLine 2\"", ss1.str());
-
- const char mutable_str[] = "\"Line\0 1\"\nLine 2";
- ::std::stringstream ss2;
- UniversalPrint(mutable_str, &ss2);
- EXPECT_EQ("\"\\\"Line\\0 1\\\"\\nLine 2\"", ss2.str());
-}
-
-TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsEmptyTuple) {
- Strings result = UniversalTersePrintTupleFieldsToStrings(::std::make_tuple());
- EXPECT_EQ(0u, result.size());
-}
-
-TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsOneTuple) {
- Strings result = UniversalTersePrintTupleFieldsToStrings(
- ::std::make_tuple(1));
- ASSERT_EQ(1u, result.size());
- EXPECT_EQ("1", result[0]);
-}
-
-TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTwoTuple) {
- Strings result = UniversalTersePrintTupleFieldsToStrings(
- ::std::make_tuple(1, 'a'));
- ASSERT_EQ(2u, result.size());
- EXPECT_EQ("1", result[0]);
- EXPECT_EQ("'a' (97, 0x61)", result[1]);
-}
-
-TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
- const int n = 1;
- Strings result = UniversalTersePrintTupleFieldsToStrings(
- ::std::tuple<const int&, const char*>(n, "a"));
- ASSERT_EQ(2u, result.size());
- EXPECT_EQ("1", result[0]);
- EXPECT_EQ("\"a\"", result[1]);
-}
-
-#if GTEST_HAS_ABSL
-
-TEST(PrintOptionalTest, Basic) {
- absl::optional<int> value;
- EXPECT_EQ("(nullopt)", PrintToString(value));
- value = {7};
- EXPECT_EQ("(7)", PrintToString(value));
- EXPECT_EQ("(1.1)", PrintToString(absl::optional<double>{1.1}));
- EXPECT_EQ("(\"A\")", PrintToString(absl::optional<std::string>{"A"}));
-}
-
-struct NonPrintable {
- unsigned char contents = 17;
-};
-
-TEST(PrintOneofTest, Basic) {
- using Type = absl::variant<int, StreamableInGlobal, NonPrintable>;
- EXPECT_EQ("('int' with value 7)", PrintToString(Type(7)));
- EXPECT_EQ("('StreamableInGlobal' with value StreamableInGlobal)",
- PrintToString(Type(StreamableInGlobal{})));
- EXPECT_EQ(
- "('testing::gtest_printers_test::NonPrintable' with value 1-byte object "
- "<11>)",
- PrintToString(Type(NonPrintable{})));
-}
-#endif // GTEST_HAS_ABSL
-namespace {
-class string_ref;
-
-/**
- * This is a synthetic pointer to a fixed size string.
- */
-class string_ptr {
- public:
- string_ptr(const char* data, size_t size) : data_(data), size_(size) {}
-
- string_ptr& operator++() noexcept {
- data_ += size_;
- return *this;
- }
-
- string_ref operator*() const noexcept;
-
- private:
- const char* data_;
- size_t size_;
-};
-
-/**
- * This is a synthetic reference of a fixed size string.
- */
-class string_ref {
- public:
- string_ref(const char* data, size_t size) : data_(data), size_(size) {}
-
- string_ptr operator&() const noexcept { return {data_, size_}; } // NOLINT
-
- bool operator==(const char* s) const noexcept {
- if (size_ > 0 && data_[size_ - 1] != 0) {
- return std::string(data_, size_) == std::string(s);
- } else {
- return std::string(data_) == std::string(s);
- }
- }
-
- private:
- const char* data_;
- size_t size_;
-};
-
-string_ref string_ptr::operator*() const noexcept { return {data_, size_}; }
-
-TEST(string_ref, compare) {
- const char* s = "alex\0davidjohn\0";
- string_ptr ptr(s, 5);
- EXPECT_EQ(*ptr, "alex");
- EXPECT_TRUE(*ptr == "alex");
- ++ptr;
- EXPECT_EQ(*ptr, "david");
- EXPECT_TRUE(*ptr == "david");
- ++ptr;
- EXPECT_EQ(*ptr, "john");
-}
-
-} // namespace
-
-} // namespace gtest_printers_test
-} // namespace testing
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2009 Google Inc. All Rights Reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Verifies that test shuffling works."""
-
-import os
-import gtest_test_utils
-
-# Command to run the googletest-shuffle-test_ program.
-COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-shuffle-test_')
-
-# The environment variables for test sharding.
-TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
-SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
-
-TEST_FILTER = 'A*.A:A*.B:C*'
-
-ALL_TESTS = []
-ACTIVE_TESTS = []
-FILTERED_TESTS = []
-SHARDED_TESTS = []
-
-SHUFFLED_ALL_TESTS = []
-SHUFFLED_ACTIVE_TESTS = []
-SHUFFLED_FILTERED_TESTS = []
-SHUFFLED_SHARDED_TESTS = []
-
-
-def AlsoRunDisabledTestsFlag():
- return '--gtest_also_run_disabled_tests'
-
-
-def FilterFlag(test_filter):
- return '--gtest_filter=%s' % (test_filter,)
-
-
-def RepeatFlag(n):
- return '--gtest_repeat=%s' % (n,)
-
-
-def ShuffleFlag():
- return '--gtest_shuffle'
-
-
-def RandomSeedFlag(n):
- return '--gtest_random_seed=%s' % (n,)
-
-
-def RunAndReturnOutput(extra_env, args):
- """Runs the test program and returns its output."""
-
- environ_copy = os.environ.copy()
- environ_copy.update(extra_env)
-
- return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
-
-
-def GetTestsForAllIterations(extra_env, args):
- """Runs the test program and returns a list of test lists.
-
- Args:
- extra_env: a map from environment variables to their values
- args: command line flags to pass to googletest-shuffle-test_
-
- Returns:
- A list where the i-th element is the list of tests run in the i-th
- test iteration.
- """
-
- test_iterations = []
- for line in RunAndReturnOutput(extra_env, args).split('\n'):
- if line.startswith('----'):
- tests = []
- test_iterations.append(tests)
- elif line.strip():
- tests.append(line.strip()) # 'TestCaseName.TestName'
-
- return test_iterations
-
-
-def GetTestCases(tests):
- """Returns a list of test cases in the given full test names.
-
- Args:
- tests: a list of full test names
-
- Returns:
- A list of test cases from 'tests', in their original order.
- Consecutive duplicates are removed.
- """
-
- test_cases = []
- for test in tests:
- test_case = test.split('.')[0]
- if not test_case in test_cases:
- test_cases.append(test_case)
-
- return test_cases
-
-
-def CalculateTestLists():
- """Calculates the list of tests run under different flags."""
-
- if not ALL_TESTS:
- ALL_TESTS.extend(
- GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0])
-
- if not ACTIVE_TESTS:
- ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
-
- if not FILTERED_TESTS:
- FILTERED_TESTS.extend(
- GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0])
-
- if not SHARDED_TESTS:
- SHARDED_TESTS.extend(
- GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
- SHARD_INDEX_ENV_VAR: '1'},
- [])[0])
-
- if not SHUFFLED_ALL_TESTS:
- SHUFFLED_ALL_TESTS.extend(GetTestsForAllIterations(
- {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)])[0])
-
- if not SHUFFLED_ACTIVE_TESTS:
- SHUFFLED_ACTIVE_TESTS.extend(GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(1)])[0])
-
- if not SHUFFLED_FILTERED_TESTS:
- SHUFFLED_FILTERED_TESTS.extend(GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)])[0])
-
- if not SHUFFLED_SHARDED_TESTS:
- SHUFFLED_SHARDED_TESTS.extend(
- GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
- SHARD_INDEX_ENV_VAR: '1'},
- [ShuffleFlag(), RandomSeedFlag(1)])[0])
-
-
-class GTestShuffleUnitTest(gtest_test_utils.TestCase):
- """Tests test shuffling."""
-
- def setUp(self):
- CalculateTestLists()
-
- def testShufflePreservesNumberOfTests(self):
- self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
- self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
- self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
- self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
-
- def testShuffleChangesTestOrder(self):
- self.assert_(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
- self.assert_(SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS)
- self.assert_(SHUFFLED_FILTERED_TESTS != FILTERED_TESTS,
- SHUFFLED_FILTERED_TESTS)
- self.assert_(SHUFFLED_SHARDED_TESTS != SHARDED_TESTS,
- SHUFFLED_SHARDED_TESTS)
-
- def testShuffleChangesTestCaseOrder(self):
- self.assert_(GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
- GetTestCases(SHUFFLED_ALL_TESTS))
- self.assert_(
- GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
- GetTestCases(SHUFFLED_ACTIVE_TESTS))
- self.assert_(
- GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
- GetTestCases(SHUFFLED_FILTERED_TESTS))
- self.assert_(
- GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
- GetTestCases(SHUFFLED_SHARDED_TESTS))
-
- def testShuffleDoesNotRepeatTest(self):
- for test in SHUFFLED_ALL_TESTS:
- self.assertEqual(1, SHUFFLED_ALL_TESTS.count(test),
- '%s appears more than once' % (test,))
- for test in SHUFFLED_ACTIVE_TESTS:
- self.assertEqual(1, SHUFFLED_ACTIVE_TESTS.count(test),
- '%s appears more than once' % (test,))
- for test in SHUFFLED_FILTERED_TESTS:
- self.assertEqual(1, SHUFFLED_FILTERED_TESTS.count(test),
- '%s appears more than once' % (test,))
- for test in SHUFFLED_SHARDED_TESTS:
- self.assertEqual(1, SHUFFLED_SHARDED_TESTS.count(test),
- '%s appears more than once' % (test,))
-
- def testShuffleDoesNotCreateNewTest(self):
- for test in SHUFFLED_ALL_TESTS:
- self.assert_(test in ALL_TESTS, '%s is an invalid test' % (test,))
- for test in SHUFFLED_ACTIVE_TESTS:
- self.assert_(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
- for test in SHUFFLED_FILTERED_TESTS:
- self.assert_(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
- for test in SHUFFLED_SHARDED_TESTS:
- self.assert_(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
-
- def testShuffleIncludesAllTests(self):
- for test in ALL_TESTS:
- self.assert_(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
- for test in ACTIVE_TESTS:
- self.assert_(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
- for test in FILTERED_TESTS:
- self.assert_(test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,))
- for test in SHARDED_TESTS:
- self.assert_(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
-
- def testShuffleLeavesDeathTestsAtFront(self):
- non_death_test_found = False
- for test in SHUFFLED_ACTIVE_TESTS:
- if 'DeathTest.' in test:
- self.assert_(not non_death_test_found,
- '%s appears after a non-death test' % (test,))
- else:
- non_death_test_found = True
-
- def _VerifyTestCasesDoNotInterleave(self, tests):
- test_cases = []
- for test in tests:
- [test_case, _] = test.split('.')
- if test_cases and test_cases[-1] != test_case:
- test_cases.append(test_case)
- self.assertEqual(1, test_cases.count(test_case),
- 'Test case %s is not grouped together in %s' %
- (test_case, tests))
-
- def testShuffleDoesNotInterleaveTestCases(self):
- self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
- self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
- self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
- self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
-
- def testShuffleRestoresOrderAfterEachIteration(self):
- # Get the test lists in all 3 iterations, using random seed 1, 2,
- # and 3 respectively. Google Test picks a different seed in each
- # iteration, and this test depends on the current implementation
- # picking successive numbers. This dependency is not ideal, but
- # makes the test much easier to write.
- [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
- GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
-
- # Make sure running the tests with random seed 1 gets the same
- # order as in iteration 1 above.
- [tests_with_seed1] = GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(1)])
- self.assertEqual(tests_in_iteration1, tests_with_seed1)
-
- # Make sure running the tests with random seed 2 gets the same
- # order as in iteration 2 above. Success means that Google Test
- # correctly restores the test order before re-shuffling at the
- # beginning of iteration 2.
- [tests_with_seed2] = GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(2)])
- self.assertEqual(tests_in_iteration2, tests_with_seed2)
-
- # Make sure running the tests with random seed 3 gets the same
- # order as in iteration 3 above. Success means that Google Test
- # correctly restores the test order before re-shuffling at the
- # beginning of iteration 3.
- [tests_with_seed3] = GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(3)])
- self.assertEqual(tests_in_iteration3, tests_with_seed3)
-
- def testShuffleGeneratesNewOrderInEachIteration(self):
- [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
- GetTestsForAllIterations(
- {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
-
- self.assert_(tests_in_iteration1 != tests_in_iteration2,
- tests_in_iteration1)
- self.assert_(tests_in_iteration1 != tests_in_iteration3,
- tests_in_iteration1)
- self.assert_(tests_in_iteration2 != tests_in_iteration3,
- tests_in_iteration2)
-
- def testShuffleShardedTestsPreservesPartition(self):
- # If we run M tests on N shards, the same M tests should be run in
- # total, regardless of the random seeds used by the shards.
- [tests1] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
- SHARD_INDEX_ENV_VAR: '0'},
- [ShuffleFlag(), RandomSeedFlag(1)])
- [tests2] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
- SHARD_INDEX_ENV_VAR: '1'},
- [ShuffleFlag(), RandomSeedFlag(20)])
- [tests3] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
- SHARD_INDEX_ENV_VAR: '2'},
- [ShuffleFlag(), RandomSeedFlag(25)])
- sorted_sharded_tests = tests1 + tests2 + tests3
- sorted_sharded_tests.sort()
- sorted_active_tests = []
- sorted_active_tests.extend(ACTIVE_TESTS)
- sorted_active_tests.sort()
- self.assertEqual(sorted_active_tests, sorted_sharded_tests)
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2009, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Verifies that test shuffling works.
-
-#include "gtest/gtest.h"
-
-namespace {
-
-using ::testing::EmptyTestEventListener;
-using ::testing::InitGoogleTest;
-using ::testing::Message;
-using ::testing::Test;
-using ::testing::TestEventListeners;
-using ::testing::TestInfo;
-using ::testing::UnitTest;
-
-// The test methods are empty, as the sole purpose of this program is
-// to print the test names before/after shuffling.
-
-class A : public Test {};
-TEST_F(A, A) {}
-TEST_F(A, B) {}
-
-TEST(ADeathTest, A) {}
-TEST(ADeathTest, B) {}
-TEST(ADeathTest, C) {}
-
-TEST(B, A) {}
-TEST(B, B) {}
-TEST(B, C) {}
-TEST(B, DISABLED_D) {}
-TEST(B, DISABLED_E) {}
-
-TEST(BDeathTest, A) {}
-TEST(BDeathTest, B) {}
-
-TEST(C, A) {}
-TEST(C, B) {}
-TEST(C, C) {}
-TEST(C, DISABLED_D) {}
-
-TEST(CDeathTest, A) {}
-
-TEST(DISABLED_D, A) {}
-TEST(DISABLED_D, DISABLED_B) {}
-
-// This printer prints the full test names only, starting each test
-// iteration with a "----" marker.
-class TestNamePrinter : public EmptyTestEventListener {
- public:
- void OnTestIterationStart(const UnitTest& /* unit_test */,
- int /* iteration */) override {
- printf("----\n");
- }
-
- void OnTestStart(const TestInfo& test_info) override {
- printf("%s.%s\n", test_info.test_case_name(), test_info.name());
- }
-};
-
-} // namespace
-
-int main(int argc, char **argv) {
- InitGoogleTest(&argc, argv);
-
- // Replaces the default printer with TestNamePrinter, which prints
- // the test name only.
- TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
- delete listeners.Release(listeners.default_result_printer());
- listeners.Append(new TestNamePrinter);
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "gtest/gtest-test-part.h"
-
-#include "gtest/gtest.h"
-
-using testing::Message;
-using testing::Test;
-using testing::TestPartResult;
-using testing::TestPartResultArray;
-
-namespace {
-
-// Tests the TestPartResult class.
-
-// The test fixture for testing TestPartResult.
-class TestPartResultTest : public Test {
- protected:
- TestPartResultTest()
- : r1_(TestPartResult::kSuccess, "foo/bar.cc", 10, "Success!"),
- r2_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure!"),
- r3_(TestPartResult::kFatalFailure, nullptr, -1, "Failure!"),
- r4_(TestPartResult::kSkip, "foo/bar.cc", 2, "Skipped!") {}
-
- TestPartResult r1_, r2_, r3_, r4_;
-};
-
-
-TEST_F(TestPartResultTest, ConstructorWorks) {
- Message message;
- message << "something is terribly wrong";
- message << static_cast<const char*>(testing::internal::kStackTraceMarker);
- message << "some unimportant stack trace";
-
- const TestPartResult result(TestPartResult::kNonFatalFailure,
- "some_file.cc",
- 42,
- message.GetString().c_str());
-
- EXPECT_EQ(TestPartResult::kNonFatalFailure, result.type());
- EXPECT_STREQ("some_file.cc", result.file_name());
- EXPECT_EQ(42, result.line_number());
- EXPECT_STREQ(message.GetString().c_str(), result.message());
- EXPECT_STREQ("something is terribly wrong", result.summary());
-}
-
-TEST_F(TestPartResultTest, ResultAccessorsWork) {
- const TestPartResult success(TestPartResult::kSuccess,
- "file.cc",
- 42,
- "message");
- EXPECT_TRUE(success.passed());
- EXPECT_FALSE(success.failed());
- EXPECT_FALSE(success.nonfatally_failed());
- EXPECT_FALSE(success.fatally_failed());
- EXPECT_FALSE(success.skipped());
-
- const TestPartResult nonfatal_failure(TestPartResult::kNonFatalFailure,
- "file.cc",
- 42,
- "message");
- EXPECT_FALSE(nonfatal_failure.passed());
- EXPECT_TRUE(nonfatal_failure.failed());
- EXPECT_TRUE(nonfatal_failure.nonfatally_failed());
- EXPECT_FALSE(nonfatal_failure.fatally_failed());
- EXPECT_FALSE(nonfatal_failure.skipped());
-
- const TestPartResult fatal_failure(TestPartResult::kFatalFailure,
- "file.cc",
- 42,
- "message");
- EXPECT_FALSE(fatal_failure.passed());
- EXPECT_TRUE(fatal_failure.failed());
- EXPECT_FALSE(fatal_failure.nonfatally_failed());
- EXPECT_TRUE(fatal_failure.fatally_failed());
- EXPECT_FALSE(fatal_failure.skipped());
-
- const TestPartResult skip(TestPartResult::kSkip, "file.cc", 42, "message");
- EXPECT_FALSE(skip.passed());
- EXPECT_FALSE(skip.failed());
- EXPECT_FALSE(skip.nonfatally_failed());
- EXPECT_FALSE(skip.fatally_failed());
- EXPECT_TRUE(skip.skipped());
-}
-
-// Tests TestPartResult::type().
-TEST_F(TestPartResultTest, type) {
- EXPECT_EQ(TestPartResult::kSuccess, r1_.type());
- EXPECT_EQ(TestPartResult::kNonFatalFailure, r2_.type());
- EXPECT_EQ(TestPartResult::kFatalFailure, r3_.type());
- EXPECT_EQ(TestPartResult::kSkip, r4_.type());
-}
-
-// Tests TestPartResult::file_name().
-TEST_F(TestPartResultTest, file_name) {
- EXPECT_STREQ("foo/bar.cc", r1_.file_name());
- EXPECT_STREQ(nullptr, r3_.file_name());
- EXPECT_STREQ("foo/bar.cc", r4_.file_name());
-}
-
-// Tests TestPartResult::line_number().
-TEST_F(TestPartResultTest, line_number) {
- EXPECT_EQ(10, r1_.line_number());
- EXPECT_EQ(-1, r2_.line_number());
- EXPECT_EQ(2, r4_.line_number());
-}
-
-// Tests TestPartResult::message().
-TEST_F(TestPartResultTest, message) {
- EXPECT_STREQ("Success!", r1_.message());
- EXPECT_STREQ("Skipped!", r4_.message());
-}
-
-// Tests TestPartResult::passed().
-TEST_F(TestPartResultTest, Passed) {
- EXPECT_TRUE(r1_.passed());
- EXPECT_FALSE(r2_.passed());
- EXPECT_FALSE(r3_.passed());
- EXPECT_FALSE(r4_.passed());
-}
-
-// Tests TestPartResult::failed().
-TEST_F(TestPartResultTest, Failed) {
- EXPECT_FALSE(r1_.failed());
- EXPECT_TRUE(r2_.failed());
- EXPECT_TRUE(r3_.failed());
- EXPECT_FALSE(r4_.failed());
-}
-
-// Tests TestPartResult::failed().
-TEST_F(TestPartResultTest, Skipped) {
- EXPECT_FALSE(r1_.skipped());
- EXPECT_FALSE(r2_.skipped());
- EXPECT_FALSE(r3_.skipped());
- EXPECT_TRUE(r4_.skipped());
-}
-
-// Tests TestPartResult::fatally_failed().
-TEST_F(TestPartResultTest, FatallyFailed) {
- EXPECT_FALSE(r1_.fatally_failed());
- EXPECT_FALSE(r2_.fatally_failed());
- EXPECT_TRUE(r3_.fatally_failed());
- EXPECT_FALSE(r4_.fatally_failed());
-}
-
-// Tests TestPartResult::nonfatally_failed().
-TEST_F(TestPartResultTest, NonfatallyFailed) {
- EXPECT_FALSE(r1_.nonfatally_failed());
- EXPECT_TRUE(r2_.nonfatally_failed());
- EXPECT_FALSE(r3_.nonfatally_failed());
- EXPECT_FALSE(r4_.nonfatally_failed());
-}
-
-// Tests the TestPartResultArray class.
-
-class TestPartResultArrayTest : public Test {
- protected:
- TestPartResultArrayTest()
- : r1_(TestPartResult::kNonFatalFailure, "foo/bar.cc", -1, "Failure 1"),
- r2_(TestPartResult::kFatalFailure, "foo/bar.cc", -1, "Failure 2") {}
-
- const TestPartResult r1_, r2_;
-};
-
-// Tests that TestPartResultArray initially has size 0.
-TEST_F(TestPartResultArrayTest, InitialSizeIsZero) {
- TestPartResultArray results;
- EXPECT_EQ(0, results.size());
-}
-
-// Tests that TestPartResultArray contains the given TestPartResult
-// after one Append() operation.
-TEST_F(TestPartResultArrayTest, ContainsGivenResultAfterAppend) {
- TestPartResultArray results;
- results.Append(r1_);
- EXPECT_EQ(1, results.size());
- EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
-}
-
-// Tests that TestPartResultArray contains the given TestPartResults
-// after two Append() operations.
-TEST_F(TestPartResultArrayTest, ContainsGivenResultsAfterTwoAppends) {
- TestPartResultArray results;
- results.Append(r1_);
- results.Append(r2_);
- EXPECT_EQ(2, results.size());
- EXPECT_STREQ("Failure 1", results.GetTestPartResult(0).message());
- EXPECT_STREQ("Failure 2", results.GetTestPartResult(1).message());
-}
-
-typedef TestPartResultArrayTest TestPartResultArrayDeathTest;
-
-// Tests that the program dies when GetTestPartResult() is called with
-// an invalid index.
-TEST_F(TestPartResultArrayDeathTest, DiesWhenIndexIsOutOfBound) {
- TestPartResultArray results;
- results.Append(r1_);
-
- EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(-1), "");
- EXPECT_DEATH_IF_SUPPORTED(results.GetTestPartResult(1), "");
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for Google Test itself. This verifies that the basic constructs of
-// Google Test work.
-
-#include "gtest/gtest.h"
-#include "googletest-param-test-test.h"
-
-using ::testing::Values;
-using ::testing::internal::ParamGenerator;
-
-// Tests that generators defined in a different translation unit
-// are functional. The test using extern_gen_2 is defined
-// in googletest-param-test-test.cc.
-ParamGenerator<int> extern_gen_2 = Values(33);
-
-// Tests that a parameterized test case can be defined in one translation unit
-// and instantiated in another. The test is defined in
-// googletest-param-test-test.cc and ExternalInstantiationTest fixture class is
-// defined in gtest-param-test_test.h.
-INSTANTIATE_TEST_SUITE_P(MultiplesOf33,
- ExternalInstantiationTest,
- Values(33, 66));
-
-// Tests that a parameterized test case can be instantiated
-// in multiple translation units. Another instantiation is defined
-// in googletest-param-test-test.cc and
-// InstantiationInMultipleTranslationUnitsTest fixture is defined in
-// gtest-param-test_test.h
-INSTANTIATE_TEST_SUITE_P(Sequence2,
- InstantiationInMultipleTranslationUnitsTest,
- Values(42*3, 42*4, 42*5));
-
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests Google Test's throw-on-failure mode with exceptions disabled.
-
-This script invokes googletest-throw-on-failure-test_ (a program written with
-Google Test) with different environments and command line flags.
-"""
-
-import os
-import gtest_test_utils
-
-
-# Constants.
-
-# The command line flag for enabling/disabling the throw-on-failure mode.
-THROW_ON_FAILURE = 'gtest_throw_on_failure'
-
-# Path to the googletest-throw-on-failure-test_ program, compiled with
-# exceptions disabled.
-EXE_PATH = gtest_test_utils.GetTestExecutablePath(
- 'googletest-throw-on-failure-test_')
-
-
-# Utilities.
-
-
-def SetEnvVar(env_var, value):
- """Sets an environment variable to a given value; unsets it when the
- given value is None.
- """
-
- env_var = env_var.upper()
- if value is not None:
- os.environ[env_var] = value
- elif env_var in os.environ:
- del os.environ[env_var]
-
-
-def Run(command):
- """Runs a command; returns True/False if its exit code is/isn't 0."""
-
- print('Running "%s". . .' % ' '.join(command))
- p = gtest_test_utils.Subprocess(command)
- return p.exited and p.exit_code == 0
-
-
-# The tests.
-class ThrowOnFailureTest(gtest_test_utils.TestCase):
- """Tests the throw-on-failure mode."""
-
- def RunAndVerify(self, env_var_value, flag_value, should_fail):
- """Runs googletest-throw-on-failure-test_ and verifies that it does
- (or does not) exit with a non-zero code.
-
- Args:
- env_var_value: value of the GTEST_BREAK_ON_FAILURE environment
- variable; None if the variable should be unset.
- flag_value: value of the --gtest_break_on_failure flag;
- None if the flag should not be present.
- should_fail: True if and only if the program is expected to fail.
- """
-
- SetEnvVar(THROW_ON_FAILURE, env_var_value)
-
- if env_var_value is None:
- env_var_value_msg = ' is not set'
- else:
- env_var_value_msg = '=' + env_var_value
-
- if flag_value is None:
- flag = ''
- elif flag_value == '0':
- flag = '--%s=0' % THROW_ON_FAILURE
- else:
- flag = '--%s' % THROW_ON_FAILURE
-
- command = [EXE_PATH]
- if flag:
- command.append(flag)
-
- if should_fail:
- should_or_not = 'should'
- else:
- should_or_not = 'should not'
-
- failed = not Run(command)
-
- SetEnvVar(THROW_ON_FAILURE, None)
-
- msg = ('when %s%s, an assertion failure in "%s" %s cause a non-zero '
- 'exit code.' %
- (THROW_ON_FAILURE, env_var_value_msg, ' '.join(command),
- should_or_not))
- self.assert_(failed == should_fail, msg)
-
- def testDefaultBehavior(self):
- """Tests the behavior of the default mode."""
-
- self.RunAndVerify(env_var_value=None, flag_value=None, should_fail=False)
-
- def testThrowOnFailureEnvVar(self):
- """Tests using the GTEST_THROW_ON_FAILURE environment variable."""
-
- self.RunAndVerify(env_var_value='0',
- flag_value=None,
- should_fail=False)
- self.RunAndVerify(env_var_value='1',
- flag_value=None,
- should_fail=True)
-
- def testThrowOnFailureFlag(self):
- """Tests using the --gtest_throw_on_failure flag."""
-
- self.RunAndVerify(env_var_value=None,
- flag_value='0',
- should_fail=False)
- self.RunAndVerify(env_var_value=None,
- flag_value='1',
- should_fail=True)
-
- def testThrowOnFailureFlagOverridesEnvVar(self):
- """Tests that --gtest_throw_on_failure overrides GTEST_THROW_ON_FAILURE."""
-
- self.RunAndVerify(env_var_value='0',
- flag_value='0',
- should_fail=False)
- self.RunAndVerify(env_var_value='0',
- flag_value='1',
- should_fail=True)
- self.RunAndVerify(env_var_value='1',
- flag_value='0',
- should_fail=False)
- self.RunAndVerify(env_var_value='1',
- flag_value='1',
- should_fail=True)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2009, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Tests Google Test's throw-on-failure mode with exceptions disabled.
-//
-// This program must be compiled with exceptions disabled. It will be
-// invoked by googletest-throw-on-failure-test.py, and is expected to exit
-// with non-zero in the throw-on-failure mode or 0 otherwise.
-
-#include "gtest/gtest.h"
-
-#include <stdio.h> // for fflush, fprintf, NULL, etc.
-#include <stdlib.h> // for exit
-#include <exception> // for set_terminate
-
-// This terminate handler aborts the program using exit() rather than abort().
-// This avoids showing pop-ups on Windows systems and core dumps on Unix-like
-// ones.
-void TerminateHandler() {
- fprintf(stderr, "%s\n", "Unhandled C++ exception terminating the program.");
- fflush(nullptr);
- exit(1);
-}
-
-int main(int argc, char** argv) {
-#if GTEST_HAS_EXCEPTIONS
- std::set_terminate(&TerminateHandler);
-#endif
- testing::InitGoogleTest(&argc, argv);
-
- // We want to ensure that people can use Google Test assertions in
- // other testing frameworks, as long as they initialize Google Test
- // properly and set the throw-on-failure mode. Therefore, we don't
- // use Google Test's constructs for defining and running tests
- // (e.g. TEST and RUN_ALL_TESTS) here.
-
- // In the throw-on-failure mode with exceptions disabled, this
- // assertion will cause the program to exit with a non-zero code.
- EXPECT_EQ(2, 3);
-
- // When not in the throw-on-failure mode, the control will reach
- // here.
- return 0;
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Verifies that Google Test warns the user when not initialized properly."""
-
-import gtest_test_utils
-
-COMMAND = gtest_test_utils.GetTestExecutablePath('googletest-uninitialized-test_')
-
-
-def Assert(condition):
- if not condition:
- raise AssertionError
-
-
-def AssertEq(expected, actual):
- if expected != actual:
- print('Expected: %s' % (expected,))
- print(' Actual: %s' % (actual,))
- raise AssertionError
-
-
-def TestExitCodeAndOutput(command):
- """Runs the given command and verifies its exit code and output."""
-
- # Verifies that 'command' exits with code 1.
- p = gtest_test_utils.Subprocess(command)
- if p.exited and p.exit_code == 0:
- Assert('IMPORTANT NOTICE' in p.output);
- Assert('InitGoogleTest' in p.output)
-
-
-class GTestUninitializedTest(gtest_test_utils.TestCase):
- def testExitCodeAndOutput(self):
- TestExitCodeAndOutput(COMMAND)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "gtest/gtest.h"
-
-TEST(DummyTest, Dummy) {
- // This test doesn't verify anything. We just need it to create a
- // realistic stage for testing the behavior of Google Test when
- // RUN_ALL_TESTS() is called without
- // testing::InitGoogleTest() being called first.
-}
-
-int main() {
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include <vector>
-
-#include "test/gtest-typed-test_test.h"
-#include "gtest/gtest.h"
-
-#if GTEST_HAS_TYPED_TEST_P
-
-// Tests that the same type-parameterized test case can be
-// instantiated in different translation units linked together.
-// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
-INSTANTIATE_TYPED_TEST_SUITE_P(Vector, ContainerTest,
- testing::Types<std::vector<int> >);
-
-#endif // GTEST_HAS_TYPED_TEST_P
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "test/gtest-typed-test_test.h"
-
-#include <set>
-#include <type_traits>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-#if _MSC_VER
-GTEST_DISABLE_MSC_WARNINGS_PUSH_(4127 /* conditional expression is constant */)
-#endif // _MSC_VER
-
-using testing::Test;
-
-// Used for testing that SetUpTestSuite()/TearDownTestSuite(), fixture
-// ctor/dtor, and SetUp()/TearDown() work correctly in typed tests and
-// type-parameterized test.
-template <typename T>
-class CommonTest : public Test {
- // For some technical reason, SetUpTestSuite() and TearDownTestSuite()
- // must be public.
- public:
- static void SetUpTestSuite() {
- shared_ = new T(5);
- }
-
- static void TearDownTestSuite() {
- delete shared_;
- shared_ = nullptr;
- }
-
- // This 'protected:' is optional. There's no harm in making all
- // members of this fixture class template public.
- protected:
- // We used to use std::list here, but switched to std::vector since
- // MSVC's <list> doesn't compile cleanly with /W4.
- typedef std::vector<T> Vector;
- typedef std::set<int> IntSet;
-
- CommonTest() : value_(1) {}
-
- ~CommonTest() override { EXPECT_EQ(3, value_); }
-
- void SetUp() override {
- EXPECT_EQ(1, value_);
- value_++;
- }
-
- void TearDown() override {
- EXPECT_EQ(2, value_);
- value_++;
- }
-
- T value_;
- static T* shared_;
-};
-
-template <typename T>
-T* CommonTest<T>::shared_ = nullptr;
-
-// This #ifdef block tests typed tests.
-#if GTEST_HAS_TYPED_TEST
-
-using testing::Types;
-
-// Tests that SetUpTestSuite()/TearDownTestSuite(), fixture ctor/dtor,
-// and SetUp()/TearDown() work correctly in typed tests
-
-typedef Types<char, int> TwoTypes;
-TYPED_TEST_SUITE(CommonTest, TwoTypes);
-
-TYPED_TEST(CommonTest, ValuesAreCorrect) {
- // Static members of the fixture class template can be visited via
- // the TestFixture:: prefix.
- EXPECT_EQ(5, *TestFixture::shared_);
-
- // Typedefs in the fixture class template can be visited via the
- // "typename TestFixture::" prefix.
- typename TestFixture::Vector empty;
- EXPECT_EQ(0U, empty.size());
-
- typename TestFixture::IntSet empty2;
- EXPECT_EQ(0U, empty2.size());
-
- // Non-static members of the fixture class must be visited via
- // 'this', as required by C++ for class templates.
- EXPECT_EQ(2, this->value_);
-}
-
-// The second test makes sure shared_ is not deleted after the first
-// test.
-TYPED_TEST(CommonTest, ValuesAreStillCorrect) {
- // Static members of the fixture class template can also be visited
- // via 'this'.
- ASSERT_TRUE(this->shared_ != nullptr);
- EXPECT_EQ(5, *this->shared_);
-
- // TypeParam can be used to refer to the type parameter.
- EXPECT_EQ(static_cast<TypeParam>(2), this->value_);
-}
-
-// Tests that multiple TYPED_TEST_SUITE's can be defined in the same
-// translation unit.
-
-template <typename T>
-class TypedTest1 : public Test {
-};
-
-// Verifies that the second argument of TYPED_TEST_SUITE can be a
-// single type.
-TYPED_TEST_SUITE(TypedTest1, int);
-TYPED_TEST(TypedTest1, A) {}
-
-template <typename T>
-class TypedTest2 : public Test {
-};
-
-// Verifies that the second argument of TYPED_TEST_SUITE can be a
-// Types<...> type list.
-TYPED_TEST_SUITE(TypedTest2, Types<int>);
-
-// This also verifies that tests from different typed test cases can
-// share the same name.
-TYPED_TEST(TypedTest2, A) {}
-
-// Tests that a typed test case can be defined in a namespace.
-
-namespace library1 {
-
-template <typename T>
-class NumericTest : public Test {
-};
-
-typedef Types<int, long> NumericTypes;
-TYPED_TEST_SUITE(NumericTest, NumericTypes);
-
-TYPED_TEST(NumericTest, DefaultIsZero) {
- EXPECT_EQ(0, TypeParam());
-}
-
-} // namespace library1
-
-// Tests that custom names work.
-template <typename T>
-class TypedTestWithNames : public Test {};
-
-class TypedTestNames {
- public:
- template <typename T>
- static std::string GetName(int i) {
- if (std::is_same<T, char>::value) {
- return std::string("char") + ::testing::PrintToString(i);
- }
- if (std::is_same<T, int>::value) {
- return std::string("int") + ::testing::PrintToString(i);
- }
- }
-};
-
-TYPED_TEST_SUITE(TypedTestWithNames, TwoTypes, TypedTestNames);
-
-TYPED_TEST(TypedTestWithNames, TestSuiteName) {
- if (std::is_same<TypeParam, char>::value) {
- EXPECT_STREQ(::testing::UnitTest::GetInstance()
- ->current_test_info()
- ->test_case_name(),
- "TypedTestWithNames/char0");
- }
- if (std::is_same<TypeParam, int>::value) {
- EXPECT_STREQ(::testing::UnitTest::GetInstance()
- ->current_test_info()
- ->test_case_name(),
- "TypedTestWithNames/int1");
- }
-}
-
-#endif // GTEST_HAS_TYPED_TEST
-
-// This #ifdef block tests type-parameterized tests.
-#if GTEST_HAS_TYPED_TEST_P
-
-using testing::Types;
-using testing::internal::TypedTestSuitePState;
-
-// Tests TypedTestSuitePState.
-
-class TypedTestSuitePStateTest : public Test {
- protected:
- void SetUp() override {
- state_.AddTestName("foo.cc", 0, "FooTest", "A");
- state_.AddTestName("foo.cc", 0, "FooTest", "B");
- state_.AddTestName("foo.cc", 0, "FooTest", "C");
- }
-
- TypedTestSuitePState state_;
-};
-
-TEST_F(TypedTestSuitePStateTest, SucceedsForMatchingList) {
- const char* tests = "A, B, C";
- EXPECT_EQ(tests,
- state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
-}
-
-// Makes sure that the order of the tests and spaces around the names
-// don't matter.
-TEST_F(TypedTestSuitePStateTest, IgnoresOrderAndSpaces) {
- const char* tests = "A,C, B";
- EXPECT_EQ(tests,
- state_.VerifyRegisteredTestNames("foo.cc", 1, tests));
-}
-
-using TypedTestSuitePStateDeathTest = TypedTestSuitePStateTest;
-
-TEST_F(TypedTestSuitePStateDeathTest, DetectsDuplicates) {
- EXPECT_DEATH_IF_SUPPORTED(
- state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, A, C"),
- "foo\\.cc.1.?: Test A is listed more than once\\.");
-}
-
-TEST_F(TypedTestSuitePStateDeathTest, DetectsExtraTest) {
- EXPECT_DEATH_IF_SUPPORTED(
- state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C, D"),
- "foo\\.cc.1.?: No test named D can be found in this test suite\\.");
-}
-
-TEST_F(TypedTestSuitePStateDeathTest, DetectsMissedTest) {
- EXPECT_DEATH_IF_SUPPORTED(
- state_.VerifyRegisteredTestNames("foo.cc", 1, "A, C"),
- "foo\\.cc.1.?: You forgot to list test B\\.");
-}
-
-// Tests that defining a test for a parameterized test case generates
-// a run-time error if the test case has been registered.
-TEST_F(TypedTestSuitePStateDeathTest, DetectsTestAfterRegistration) {
- state_.VerifyRegisteredTestNames("foo.cc", 1, "A, B, C");
- EXPECT_DEATH_IF_SUPPORTED(
- state_.AddTestName("foo.cc", 2, "FooTest", "D"),
- "foo\\.cc.2.?: Test D must be defined before REGISTER_TYPED_TEST_SUITE_P"
- "\\(FooTest, \\.\\.\\.\\)\\.");
-}
-
-// Tests that SetUpTestSuite()/TearDownTestSuite(), fixture ctor/dtor,
-// and SetUp()/TearDown() work correctly in type-parameterized tests.
-
-template <typename T>
-class DerivedTest : public CommonTest<T> {
-};
-
-TYPED_TEST_SUITE_P(DerivedTest);
-
-TYPED_TEST_P(DerivedTest, ValuesAreCorrect) {
- // Static members of the fixture class template can be visited via
- // the TestFixture:: prefix.
- EXPECT_EQ(5, *TestFixture::shared_);
-
- // Non-static members of the fixture class must be visited via
- // 'this', as required by C++ for class templates.
- EXPECT_EQ(2, this->value_);
-}
-
-// The second test makes sure shared_ is not deleted after the first
-// test.
-TYPED_TEST_P(DerivedTest, ValuesAreStillCorrect) {
- // Static members of the fixture class template can also be visited
- // via 'this'.
- ASSERT_TRUE(this->shared_ != nullptr);
- EXPECT_EQ(5, *this->shared_);
- EXPECT_EQ(2, this->value_);
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DerivedTest,
- ValuesAreCorrect, ValuesAreStillCorrect);
-
-typedef Types<short, long> MyTwoTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(My, DerivedTest, MyTwoTypes);
-
-// Tests that custom names work with type parametrized tests. We reuse the
-// TwoTypes from above here.
-template <typename T>
-class TypeParametrizedTestWithNames : public Test {};
-
-TYPED_TEST_SUITE_P(TypeParametrizedTestWithNames);
-
-TYPED_TEST_P(TypeParametrizedTestWithNames, TestSuiteName) {
- if (std::is_same<TypeParam, char>::value) {
- EXPECT_STREQ(::testing::UnitTest::GetInstance()
- ->current_test_info()
- ->test_case_name(),
- "CustomName/TypeParametrizedTestWithNames/parChar0");
- }
- if (std::is_same<TypeParam, int>::value) {
- EXPECT_STREQ(::testing::UnitTest::GetInstance()
- ->current_test_info()
- ->test_case_name(),
- "CustomName/TypeParametrizedTestWithNames/parInt1");
- }
-}
-
-REGISTER_TYPED_TEST_SUITE_P(TypeParametrizedTestWithNames, TestSuiteName);
-
-class TypeParametrizedTestNames {
- public:
- template <typename T>
- static std::string GetName(int i) {
- if (std::is_same<T, char>::value) {
- return std::string("parChar") + ::testing::PrintToString(i);
- }
- if (std::is_same<T, int>::value) {
- return std::string("parInt") + ::testing::PrintToString(i);
- }
- }
-};
-
-INSTANTIATE_TYPED_TEST_SUITE_P(CustomName, TypeParametrizedTestWithNames,
- TwoTypes, TypeParametrizedTestNames);
-
-// Tests that multiple TYPED_TEST_SUITE_P's can be defined in the same
-// translation unit.
-
-template <typename T>
-class TypedTestP1 : public Test {
-};
-
-TYPED_TEST_SUITE_P(TypedTestP1);
-
-// For testing that the code between TYPED_TEST_SUITE_P() and
-// TYPED_TEST_P() is not enclosed in a namespace.
-using IntAfterTypedTestSuiteP = int;
-
-TYPED_TEST_P(TypedTestP1, A) {}
-TYPED_TEST_P(TypedTestP1, B) {}
-
-// For testing that the code between TYPED_TEST_P() and
-// REGISTER_TYPED_TEST_SUITE_P() is not enclosed in a namespace.
-using IntBeforeRegisterTypedTestSuiteP = int;
-
-REGISTER_TYPED_TEST_SUITE_P(TypedTestP1, A, B);
-
-template <typename T>
-class TypedTestP2 : public Test {
-};
-
-TYPED_TEST_SUITE_P(TypedTestP2);
-
-// This also verifies that tests from different type-parameterized
-// test cases can share the same name.
-TYPED_TEST_P(TypedTestP2, A) {}
-
-REGISTER_TYPED_TEST_SUITE_P(TypedTestP2, A);
-
-// Verifies that the code between TYPED_TEST_SUITE_P() and
-// REGISTER_TYPED_TEST_SUITE_P() is not enclosed in a namespace.
-IntAfterTypedTestSuiteP after = 0;
-IntBeforeRegisterTypedTestSuiteP before = 0;
-
-// Verifies that the last argument of INSTANTIATE_TYPED_TEST_SUITE_P()
-// can be either a single type or a Types<...> type list.
-INSTANTIATE_TYPED_TEST_SUITE_P(Int, TypedTestP1, int);
-INSTANTIATE_TYPED_TEST_SUITE_P(Int, TypedTestP2, Types<int>);
-
-// Tests that the same type-parameterized test case can be
-// instantiated more than once in the same translation unit.
-INSTANTIATE_TYPED_TEST_SUITE_P(Double, TypedTestP2, Types<double>);
-
-// Tests that the same type-parameterized test case can be
-// instantiated in different translation units linked together.
-// (ContainerTest is also instantiated in gtest-typed-test_test.cc.)
-typedef Types<std::vector<double>, std::set<char> > MyContainers;
-INSTANTIATE_TYPED_TEST_SUITE_P(My, ContainerTest, MyContainers);
-
-// Tests that a type-parameterized test case can be defined and
-// instantiated in a namespace.
-
-namespace library2 {
-
-template <typename T>
-class NumericTest : public Test {
-};
-
-TYPED_TEST_SUITE_P(NumericTest);
-
-TYPED_TEST_P(NumericTest, DefaultIsZero) {
- EXPECT_EQ(0, TypeParam());
-}
-
-TYPED_TEST_P(NumericTest, ZeroIsLessThanOne) {
- EXPECT_LT(TypeParam(0), TypeParam(1));
-}
-
-REGISTER_TYPED_TEST_SUITE_P(NumericTest,
- DefaultIsZero, ZeroIsLessThanOne);
-typedef Types<int, double> NumericTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(My, NumericTest, NumericTypes);
-
-static const char* GetTestName() {
- return testing::UnitTest::GetInstance()->current_test_info()->name();
-}
-// Test the stripping of space from test names
-template <typename T> class TrimmedTest : public Test { };
-TYPED_TEST_SUITE_P(TrimmedTest);
-TYPED_TEST_P(TrimmedTest, Test1) { EXPECT_STREQ("Test1", GetTestName()); }
-TYPED_TEST_P(TrimmedTest, Test2) { EXPECT_STREQ("Test2", GetTestName()); }
-TYPED_TEST_P(TrimmedTest, Test3) { EXPECT_STREQ("Test3", GetTestName()); }
-TYPED_TEST_P(TrimmedTest, Test4) { EXPECT_STREQ("Test4", GetTestName()); }
-TYPED_TEST_P(TrimmedTest, Test5) { EXPECT_STREQ("Test5", GetTestName()); }
-REGISTER_TYPED_TEST_SUITE_P(
- TrimmedTest,
- Test1, Test2,Test3 , Test4 ,Test5 ); // NOLINT
-template <typename T1, typename T2> struct MyPair {};
-// Be sure to try a type with a comma in its name just in case it matters.
-typedef Types<int, double, MyPair<int, int> > TrimTypes;
-INSTANTIATE_TYPED_TEST_SUITE_P(My, TrimmedTest, TrimTypes);
-
-} // namespace library2
-
-#endif // GTEST_HAS_TYPED_TEST_P
-
-#if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
-
-// Google Test may not support type-parameterized tests with some
-// compilers. If we use conditional compilation to compile out all
-// code referring to the gtest_main library, MSVC linker will not link
-// that library at all and consequently complain about missing entry
-// point defined in that library (fatal error LNK1561: entry point
-// must be defined). This dummy test keeps gtest_main linked in.
-TEST(DummyTest, TypedTestsAreNotSupportedOnThisPlatform) {}
-
-#if _MSC_VER
-GTEST_DISABLE_MSC_WARNINGS_POP_() // 4127
-#endif // _MSC_VER
-
-#endif // #if !defined(GTEST_HAS_TYPED_TEST) && !defined(GTEST_HAS_TYPED_TEST_P)
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#ifndef GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
-#define GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
-
-#include "gtest/gtest.h"
-
-#if GTEST_HAS_TYPED_TEST_P
-
-using testing::Test;
-
-// For testing that the same type-parameterized test case can be
-// instantiated in different translation units linked together.
-// ContainerTest will be instantiated in both gtest-typed-test_test.cc
-// and gtest-typed-test2_test.cc.
-
-template <typename T>
-class ContainerTest : public Test {
-};
-
-TYPED_TEST_SUITE_P(ContainerTest);
-
-TYPED_TEST_P(ContainerTest, CanBeDefaultConstructed) {
- TypeParam container;
-}
-
-TYPED_TEST_P(ContainerTest, InitialSizeIsZero) {
- TypeParam container;
- EXPECT_EQ(0U, container.size());
-}
-
-REGISTER_TYPED_TEST_SUITE_P(ContainerTest,
- CanBeDefaultConstructed, InitialSizeIsZero);
-
-#endif // GTEST_HAS_TYPED_TEST_P
-
-#endif // GTEST_TEST_GTEST_TYPED_TEST_TEST_H_
+++ /dev/null
-// Copyright 2009 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// The Google C++ Testing and Mocking Framework (Google Test)
-//
-// This file contains tests verifying correctness of data provided via
-// UnitTest's public methods.
-
-#include "gtest/gtest.h"
-
-#include <string.h> // For strcmp.
-#include <algorithm>
-
-using ::testing::InitGoogleTest;
-
-namespace testing {
-namespace internal {
-
-template <typename T>
-struct LessByName {
- bool operator()(const T* a, const T* b) {
- return strcmp(a->name(), b->name()) < 0;
- }
-};
-
-class UnitTestHelper {
- public:
- // Returns the array of pointers to all test suites sorted by the test suite
- // name. The caller is responsible for deleting the array.
- static TestSuite const** GetSortedTestSuites() {
- UnitTest& unit_test = *UnitTest::GetInstance();
- auto const** const test_suites =
- new const TestSuite*[unit_test.total_test_suite_count()];
-
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i)
- test_suites[i] = unit_test.GetTestSuite(i);
-
- std::sort(test_suites,
- test_suites + unit_test.total_test_suite_count(),
- LessByName<TestSuite>());
- return test_suites;
- }
-
- // Returns the test suite by its name. The caller doesn't own the returned
- // pointer.
- static const TestSuite* FindTestSuite(const char* name) {
- UnitTest& unit_test = *UnitTest::GetInstance();
- for (int i = 0; i < unit_test.total_test_suite_count(); ++i) {
- const TestSuite* test_suite = unit_test.GetTestSuite(i);
- if (0 == strcmp(test_suite->name(), name))
- return test_suite;
- }
- return nullptr;
- }
-
- // Returns the array of pointers to all tests in a particular test suite
- // sorted by the test name. The caller is responsible for deleting the
- // array.
- static TestInfo const** GetSortedTests(const TestSuite* test_suite) {
- TestInfo const** const tests =
- new const TestInfo*[test_suite->total_test_count()];
-
- for (int i = 0; i < test_suite->total_test_count(); ++i)
- tests[i] = test_suite->GetTestInfo(i);
-
- std::sort(tests, tests + test_suite->total_test_count(),
- LessByName<TestInfo>());
- return tests;
- }
-};
-
-#if GTEST_HAS_TYPED_TEST
-template <typename T> class TestSuiteWithCommentTest : public Test {};
-TYPED_TEST_SUITE(TestSuiteWithCommentTest, Types<int>);
-TYPED_TEST(TestSuiteWithCommentTest, Dummy) {}
-
-const int kTypedTestSuites = 1;
-const int kTypedTests = 1;
-#else
-const int kTypedTestSuites = 0;
-const int kTypedTests = 0;
-#endif // GTEST_HAS_TYPED_TEST
-
-// We can only test the accessors that do not change value while tests run.
-// Since tests can be run in any order, the values the accessors that track
-// test execution (such as failed_test_count) can not be predicted.
-TEST(ApiTest, UnitTestImmutableAccessorsWork) {
- UnitTest* unit_test = UnitTest::GetInstance();
-
- ASSERT_EQ(2 + kTypedTestSuites, unit_test->total_test_suite_count());
- EXPECT_EQ(1 + kTypedTestSuites, unit_test->test_suite_to_run_count());
- EXPECT_EQ(2, unit_test->disabled_test_count());
- EXPECT_EQ(5 + kTypedTests, unit_test->total_test_count());
- EXPECT_EQ(3 + kTypedTests, unit_test->test_to_run_count());
-
- const TestSuite** const test_suites = UnitTestHelper::GetSortedTestSuites();
-
- EXPECT_STREQ("ApiTest", test_suites[0]->name());
- EXPECT_STREQ("DISABLED_Test", test_suites[1]->name());
-#if GTEST_HAS_TYPED_TEST
- EXPECT_STREQ("TestSuiteWithCommentTest/0", test_suites[2]->name());
-#endif // GTEST_HAS_TYPED_TEST
-
- delete[] test_suites;
-
- // The following lines initiate actions to verify certain methods in
- // FinalSuccessChecker::TearDown.
-
- // Records a test property to verify TestResult::GetTestProperty().
- RecordProperty("key", "value");
-}
-
-AssertionResult IsNull(const char* str) {
- if (str != nullptr) {
- return testing::AssertionFailure() << "argument is " << str;
- }
- return AssertionSuccess();
-}
-
-TEST(ApiTest, TestSuiteImmutableAccessorsWork) {
- const TestSuite* test_suite = UnitTestHelper::FindTestSuite("ApiTest");
- ASSERT_TRUE(test_suite != nullptr);
-
- EXPECT_STREQ("ApiTest", test_suite->name());
- EXPECT_TRUE(IsNull(test_suite->type_param()));
- EXPECT_TRUE(test_suite->should_run());
- EXPECT_EQ(1, test_suite->disabled_test_count());
- EXPECT_EQ(3, test_suite->test_to_run_count());
- ASSERT_EQ(4, test_suite->total_test_count());
-
- const TestInfo** tests = UnitTestHelper::GetSortedTests(test_suite);
-
- EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
- EXPECT_STREQ("ApiTest", tests[0]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[0]->value_param()));
- EXPECT_TRUE(IsNull(tests[0]->type_param()));
- EXPECT_FALSE(tests[0]->should_run());
-
- EXPECT_STREQ("TestSuiteDisabledAccessorsWork", tests[1]->name());
- EXPECT_STREQ("ApiTest", tests[1]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[1]->value_param()));
- EXPECT_TRUE(IsNull(tests[1]->type_param()));
- EXPECT_TRUE(tests[1]->should_run());
-
- EXPECT_STREQ("TestSuiteImmutableAccessorsWork", tests[2]->name());
- EXPECT_STREQ("ApiTest", tests[2]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[2]->value_param()));
- EXPECT_TRUE(IsNull(tests[2]->type_param()));
- EXPECT_TRUE(tests[2]->should_run());
-
- EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
- EXPECT_STREQ("ApiTest", tests[3]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[3]->value_param()));
- EXPECT_TRUE(IsNull(tests[3]->type_param()));
- EXPECT_TRUE(tests[3]->should_run());
-
- delete[] tests;
- tests = nullptr;
-
-#if GTEST_HAS_TYPED_TEST
- test_suite = UnitTestHelper::FindTestSuite("TestSuiteWithCommentTest/0");
- ASSERT_TRUE(test_suite != nullptr);
-
- EXPECT_STREQ("TestSuiteWithCommentTest/0", test_suite->name());
- EXPECT_STREQ(GetTypeName<int>().c_str(), test_suite->type_param());
- EXPECT_TRUE(test_suite->should_run());
- EXPECT_EQ(0, test_suite->disabled_test_count());
- EXPECT_EQ(1, test_suite->test_to_run_count());
- ASSERT_EQ(1, test_suite->total_test_count());
-
- tests = UnitTestHelper::GetSortedTests(test_suite);
-
- EXPECT_STREQ("Dummy", tests[0]->name());
- EXPECT_STREQ("TestSuiteWithCommentTest/0", tests[0]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[0]->value_param()));
- EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
- EXPECT_TRUE(tests[0]->should_run());
-
- delete[] tests;
-#endif // GTEST_HAS_TYPED_TEST
-}
-
-TEST(ApiTest, TestSuiteDisabledAccessorsWork) {
- const TestSuite* test_suite = UnitTestHelper::FindTestSuite("DISABLED_Test");
- ASSERT_TRUE(test_suite != nullptr);
-
- EXPECT_STREQ("DISABLED_Test", test_suite->name());
- EXPECT_TRUE(IsNull(test_suite->type_param()));
- EXPECT_FALSE(test_suite->should_run());
- EXPECT_EQ(1, test_suite->disabled_test_count());
- EXPECT_EQ(0, test_suite->test_to_run_count());
- ASSERT_EQ(1, test_suite->total_test_count());
-
- const TestInfo* const test_info = test_suite->GetTestInfo(0);
- EXPECT_STREQ("Dummy2", test_info->name());
- EXPECT_STREQ("DISABLED_Test", test_info->test_suite_name());
- EXPECT_TRUE(IsNull(test_info->value_param()));
- EXPECT_TRUE(IsNull(test_info->type_param()));
- EXPECT_FALSE(test_info->should_run());
-}
-
-// These two tests are here to provide support for testing
-// test_suite_to_run_count, disabled_test_count, and test_to_run_count.
-TEST(ApiTest, DISABLED_Dummy1) {}
-TEST(DISABLED_Test, Dummy2) {}
-
-class FinalSuccessChecker : public Environment {
- protected:
- void TearDown() override {
- UnitTest* unit_test = UnitTest::GetInstance();
-
- EXPECT_EQ(1 + kTypedTestSuites, unit_test->successful_test_suite_count());
- EXPECT_EQ(3 + kTypedTests, unit_test->successful_test_count());
- EXPECT_EQ(0, unit_test->failed_test_suite_count());
- EXPECT_EQ(0, unit_test->failed_test_count());
- EXPECT_TRUE(unit_test->Passed());
- EXPECT_FALSE(unit_test->Failed());
- ASSERT_EQ(2 + kTypedTestSuites, unit_test->total_test_suite_count());
-
- const TestSuite** const test_suites = UnitTestHelper::GetSortedTestSuites();
-
- EXPECT_STREQ("ApiTest", test_suites[0]->name());
- EXPECT_TRUE(IsNull(test_suites[0]->type_param()));
- EXPECT_TRUE(test_suites[0]->should_run());
- EXPECT_EQ(1, test_suites[0]->disabled_test_count());
- ASSERT_EQ(4, test_suites[0]->total_test_count());
- EXPECT_EQ(3, test_suites[0]->successful_test_count());
- EXPECT_EQ(0, test_suites[0]->failed_test_count());
- EXPECT_TRUE(test_suites[0]->Passed());
- EXPECT_FALSE(test_suites[0]->Failed());
-
- EXPECT_STREQ("DISABLED_Test", test_suites[1]->name());
- EXPECT_TRUE(IsNull(test_suites[1]->type_param()));
- EXPECT_FALSE(test_suites[1]->should_run());
- EXPECT_EQ(1, test_suites[1]->disabled_test_count());
- ASSERT_EQ(1, test_suites[1]->total_test_count());
- EXPECT_EQ(0, test_suites[1]->successful_test_count());
- EXPECT_EQ(0, test_suites[1]->failed_test_count());
-
-#if GTEST_HAS_TYPED_TEST
- EXPECT_STREQ("TestSuiteWithCommentTest/0", test_suites[2]->name());
- EXPECT_STREQ(GetTypeName<int>().c_str(), test_suites[2]->type_param());
- EXPECT_TRUE(test_suites[2]->should_run());
- EXPECT_EQ(0, test_suites[2]->disabled_test_count());
- ASSERT_EQ(1, test_suites[2]->total_test_count());
- EXPECT_EQ(1, test_suites[2]->successful_test_count());
- EXPECT_EQ(0, test_suites[2]->failed_test_count());
- EXPECT_TRUE(test_suites[2]->Passed());
- EXPECT_FALSE(test_suites[2]->Failed());
-#endif // GTEST_HAS_TYPED_TEST
-
- const TestSuite* test_suite = UnitTestHelper::FindTestSuite("ApiTest");
- const TestInfo** tests = UnitTestHelper::GetSortedTests(test_suite);
- EXPECT_STREQ("DISABLED_Dummy1", tests[0]->name());
- EXPECT_STREQ("ApiTest", tests[0]->test_suite_name());
- EXPECT_FALSE(tests[0]->should_run());
-
- EXPECT_STREQ("TestSuiteDisabledAccessorsWork", tests[1]->name());
- EXPECT_STREQ("ApiTest", tests[1]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[1]->value_param()));
- EXPECT_TRUE(IsNull(tests[1]->type_param()));
- EXPECT_TRUE(tests[1]->should_run());
- EXPECT_TRUE(tests[1]->result()->Passed());
- EXPECT_EQ(0, tests[1]->result()->test_property_count());
-
- EXPECT_STREQ("TestSuiteImmutableAccessorsWork", tests[2]->name());
- EXPECT_STREQ("ApiTest", tests[2]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[2]->value_param()));
- EXPECT_TRUE(IsNull(tests[2]->type_param()));
- EXPECT_TRUE(tests[2]->should_run());
- EXPECT_TRUE(tests[2]->result()->Passed());
- EXPECT_EQ(0, tests[2]->result()->test_property_count());
-
- EXPECT_STREQ("UnitTestImmutableAccessorsWork", tests[3]->name());
- EXPECT_STREQ("ApiTest", tests[3]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[3]->value_param()));
- EXPECT_TRUE(IsNull(tests[3]->type_param()));
- EXPECT_TRUE(tests[3]->should_run());
- EXPECT_TRUE(tests[3]->result()->Passed());
- EXPECT_EQ(1, tests[3]->result()->test_property_count());
- const TestProperty& property = tests[3]->result()->GetTestProperty(0);
- EXPECT_STREQ("key", property.key());
- EXPECT_STREQ("value", property.value());
-
- delete[] tests;
-
-#if GTEST_HAS_TYPED_TEST
- test_suite = UnitTestHelper::FindTestSuite("TestSuiteWithCommentTest/0");
- tests = UnitTestHelper::GetSortedTests(test_suite);
-
- EXPECT_STREQ("Dummy", tests[0]->name());
- EXPECT_STREQ("TestSuiteWithCommentTest/0", tests[0]->test_suite_name());
- EXPECT_TRUE(IsNull(tests[0]->value_param()));
- EXPECT_STREQ(GetTypeName<int>().c_str(), tests[0]->type_param());
- EXPECT_TRUE(tests[0]->should_run());
- EXPECT_TRUE(tests[0]->result()->Passed());
- EXPECT_EQ(0, tests[0]->result()->test_property_count());
-
- delete[] tests;
-#endif // GTEST_HAS_TYPED_TEST
- delete[] test_suites;
- }
-};
-
-} // namespace internal
-} // namespace testing
-
-int main(int argc, char **argv) {
- InitGoogleTest(&argc, argv);
-
- AddGlobalTestEnvironment(new testing::internal::FinalSuccessChecker());
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2009, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for Google C++ Testing and Mocking Framework (Google Test)
-//
-// Sometimes it's desirable to build most of Google Test's own tests
-// by compiling a single file. This file serves this purpose.
-#include "test/googletest-filepath-test.cc"
-#include "test/googletest-message-test.cc"
-#include "test/googletest-options-test.cc"
-#include "test/googletest-port-test.cc"
-#include "test/googletest-test-part-test.cc"
-#include "test/gtest-typed-test2_test.cc"
-#include "test/gtest-typed-test_test.cc"
-#include "test/gtest_pred_impl_unittest.cc"
-#include "test/gtest_prod_test.cc"
-#include "test/gtest_skip_test.cc"
-#include "test/gtest_unittest.cc"
-#include "test/production.cc"
+++ /dev/null
-// Copyright 2009, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Tests Google Test's assert-by-exception mode with exceptions enabled.
-
-#include "gtest/gtest.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdexcept>
-
-class ThrowListener : public testing::EmptyTestEventListener {
- void OnTestPartResult(const testing::TestPartResult& result) override {
- if (result.type() == testing::TestPartResult::kFatalFailure) {
- throw testing::AssertionException(result);
- }
- }
-};
-
-// Prints the given failure message and exits the program with
-// non-zero. We use this instead of a Google Test assertion to
-// indicate a failure, as the latter is been tested and cannot be
-// relied on.
-void Fail(const char* msg) {
- printf("FAILURE: %s\n", msg);
- fflush(stdout);
- exit(1);
-}
-
-static void AssertFalse() {
- ASSERT_EQ(2, 3) << "Expected failure";
-}
-
-// Tests that an assertion failure throws a subclass of
-// std::runtime_error.
-TEST(Test, Test) {
- // A successful assertion shouldn't throw.
- try {
- EXPECT_EQ(3, 3);
- } catch(...) {
- Fail("A successful assertion wrongfully threw.");
- }
-
- // A successful assertion shouldn't throw.
- try {
- EXPECT_EQ(3, 4);
- } catch(...) {
- Fail("A failed non-fatal assertion wrongfully threw.");
- }
-
- // A failed assertion should throw.
- try {
- AssertFalse();
- } catch(const testing::AssertionException& e) {
- if (strstr(e.what(), "Expected failure") != nullptr) throw;
-
- printf("%s",
- "A failed assertion did throw an exception of the right type, "
- "but the message is incorrect. Instead of containing \"Expected "
- "failure\", it is:\n");
- Fail(e.what());
- } catch(...) {
- Fail("A failed assertion threw the wrong type of exception.");
- }
- Fail("A failed assertion should've thrown but didn't.");
-}
-
-int kTestForContinuingTest = 0;
-
-TEST(Test, Test2) {
- kTestForContinuingTest = 1;
-}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
- testing::UnitTest::GetInstance()->listeners().Append(new ThrowListener);
-
- int result = RUN_ALL_TESTS();
- if (result == 0) {
- printf("RUN_ALL_TESTS returned %d\n", result);
- Fail("Expected failure instead.");
- }
-
- if (kTestForContinuingTest == 0) {
- Fail("Should have continued with other tests, but did not.");
- }
- return 0;
-}
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests using global test environments.
-
-#include <stdlib.h>
-#include <stdio.h>
-#include "gtest/gtest.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-GTEST_DECLARE_string_(filter);
-}
-
-namespace {
-
-enum FailureType {
- NO_FAILURE, NON_FATAL_FAILURE, FATAL_FAILURE
-};
-
-// For testing using global test environments.
-class MyEnvironment : public testing::Environment {
- public:
- MyEnvironment() { Reset(); }
-
- // Depending on the value of failure_in_set_up_, SetUp() will
- // generate a non-fatal failure, generate a fatal failure, or
- // succeed.
- void SetUp() override {
- set_up_was_run_ = true;
-
- switch (failure_in_set_up_) {
- case NON_FATAL_FAILURE:
- ADD_FAILURE() << "Expected non-fatal failure in global set-up.";
- break;
- case FATAL_FAILURE:
- FAIL() << "Expected fatal failure in global set-up.";
- break;
- default:
- break;
- }
- }
-
- // Generates a non-fatal failure.
- void TearDown() override {
- tear_down_was_run_ = true;
- ADD_FAILURE() << "Expected non-fatal failure in global tear-down.";
- }
-
- // Resets the state of the environment s.t. it can be reused.
- void Reset() {
- failure_in_set_up_ = NO_FAILURE;
- set_up_was_run_ = false;
- tear_down_was_run_ = false;
- }
-
- // We call this function to set the type of failure SetUp() should
- // generate.
- void set_failure_in_set_up(FailureType type) {
- failure_in_set_up_ = type;
- }
-
- // Was SetUp() run?
- bool set_up_was_run() const { return set_up_was_run_; }
-
- // Was TearDown() run?
- bool tear_down_was_run() const { return tear_down_was_run_; }
-
- private:
- FailureType failure_in_set_up_;
- bool set_up_was_run_;
- bool tear_down_was_run_;
-};
-
-// Was the TEST run?
-bool test_was_run;
-
-// The sole purpose of this TEST is to enable us to check whether it
-// was run.
-TEST(FooTest, Bar) {
- test_was_run = true;
-}
-
-// Prints the message and aborts the program if condition is false.
-void Check(bool condition, const char* msg) {
- if (!condition) {
- printf("FAILED: %s\n", msg);
- testing::internal::posix::Abort();
- }
-}
-
-// Runs the tests. Return true if and only if successful.
-//
-// The 'failure' parameter specifies the type of failure that should
-// be generated by the global set-up.
-int RunAllTests(MyEnvironment* env, FailureType failure) {
- env->Reset();
- env->set_failure_in_set_up(failure);
- test_was_run = false;
- testing::internal::GetUnitTestImpl()->ClearAdHocTestResult();
- return RUN_ALL_TESTS();
-}
-
-} // namespace
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
-
- // Registers a global test environment, and verifies that the
- // registration function returns its argument.
- MyEnvironment* const env = new MyEnvironment;
- Check(testing::AddGlobalTestEnvironment(env) == env,
- "AddGlobalTestEnvironment() should return its argument.");
-
- // Verifies that RUN_ALL_TESTS() runs the tests when the global
- // set-up is successful.
- Check(RunAllTests(env, NO_FAILURE) != 0,
- "RUN_ALL_TESTS() should return non-zero, as the global tear-down "
- "should generate a failure.");
- Check(test_was_run,
- "The tests should run, as the global set-up should generate no "
- "failure");
- Check(env->tear_down_was_run(),
- "The global tear-down should run, as the global set-up was run.");
-
- // Verifies that RUN_ALL_TESTS() runs the tests when the global
- // set-up generates no fatal failure.
- Check(RunAllTests(env, NON_FATAL_FAILURE) != 0,
- "RUN_ALL_TESTS() should return non-zero, as both the global set-up "
- "and the global tear-down should generate a non-fatal failure.");
- Check(test_was_run,
- "The tests should run, as the global set-up should generate no "
- "fatal failure.");
- Check(env->tear_down_was_run(),
- "The global tear-down should run, as the global set-up was run.");
-
- // Verifies that RUN_ALL_TESTS() runs no test when the global set-up
- // generates a fatal failure.
- Check(RunAllTests(env, FATAL_FAILURE) != 0,
- "RUN_ALL_TESTS() should return non-zero, as the global set-up "
- "should generate a fatal failure.");
- Check(!test_was_run,
- "The tests should not run, as the global set-up should generate "
- "a fatal failure.");
- Check(env->tear_down_was_run(),
- "The global tear-down should run, as the global set-up was run.");
-
- // Verifies that RUN_ALL_TESTS() doesn't do global set-up or
- // tear-down when there is no test to run.
- testing::GTEST_FLAG(filter) = "-*";
- Check(RunAllTests(env, NO_FAILURE) == 0,
- "RUN_ALL_TESTS() should return zero, as there is no test to run.");
- Check(!env->set_up_was_run(),
- "The global set-up should not run, as there is no test to run.");
- Check(!env->tear_down_was_run(),
- "The global tear-down should not run, "
- "as the global set-up was not run.");
-
- printf("PASS\n");
- return 0;
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests the --help flag of Google C++ Testing and Mocking Framework.
-
-SYNOPSIS
- gtest_help_test.py --build_dir=BUILD/DIR
- # where BUILD/DIR contains the built gtest_help_test_ file.
- gtest_help_test.py
-"""
-
-import os
-import re
-import gtest_test_utils
-
-
-IS_LINUX = os.name == 'posix' and os.uname()[0] == 'Linux'
-IS_WINDOWS = os.name == 'nt'
-
-PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath('gtest_help_test_')
-FLAG_PREFIX = '--gtest_'
-DEATH_TEST_STYLE_FLAG = FLAG_PREFIX + 'death_test_style'
-STREAM_RESULT_TO_FLAG = FLAG_PREFIX + 'stream_result_to'
-UNKNOWN_FLAG = FLAG_PREFIX + 'unknown_flag_for_testing'
-LIST_TESTS_FLAG = FLAG_PREFIX + 'list_tests'
-INCORRECT_FLAG_VARIANTS = [re.sub('^--', '-', LIST_TESTS_FLAG),
- re.sub('^--', '/', LIST_TESTS_FLAG),
- re.sub('_', '-', LIST_TESTS_FLAG)]
-INTERNAL_FLAG_FOR_TESTING = FLAG_PREFIX + 'internal_flag_for_testing'
-
-SUPPORTS_DEATH_TESTS = "DeathTest" in gtest_test_utils.Subprocess(
- [PROGRAM_PATH, LIST_TESTS_FLAG]).output
-
-# The help message must match this regex.
-HELP_REGEX = re.compile(
- FLAG_PREFIX + r'list_tests.*' +
- FLAG_PREFIX + r'filter=.*' +
- FLAG_PREFIX + r'also_run_disabled_tests.*' +
- FLAG_PREFIX + r'repeat=.*' +
- FLAG_PREFIX + r'shuffle.*' +
- FLAG_PREFIX + r'random_seed=.*' +
- FLAG_PREFIX + r'color=.*' +
- FLAG_PREFIX + r'print_time.*' +
- FLAG_PREFIX + r'output=.*' +
- FLAG_PREFIX + r'break_on_failure.*' +
- FLAG_PREFIX + r'throw_on_failure.*' +
- FLAG_PREFIX + r'catch_exceptions=0.*',
- re.DOTALL)
-
-
-def RunWithFlag(flag):
- """Runs gtest_help_test_ with the given flag.
-
- Returns:
- the exit code and the text output as a tuple.
- Args:
- flag: the command-line flag to pass to gtest_help_test_, or None.
- """
-
- if flag is None:
- command = [PROGRAM_PATH]
- else:
- command = [PROGRAM_PATH, flag]
- child = gtest_test_utils.Subprocess(command)
- return child.exit_code, child.output
-
-
-class GTestHelpTest(gtest_test_utils.TestCase):
- """Tests the --help flag and its equivalent forms."""
-
- def TestHelpFlag(self, flag):
- """Verifies correct behavior when help flag is specified.
-
- The right message must be printed and the tests must
- skipped when the given flag is specified.
-
- Args:
- flag: A flag to pass to the binary or None.
- """
-
- exit_code, output = RunWithFlag(flag)
- self.assertEquals(0, exit_code)
- self.assert_(HELP_REGEX.search(output), output)
-
- if IS_LINUX:
- self.assert_(STREAM_RESULT_TO_FLAG in output, output)
- else:
- self.assert_(STREAM_RESULT_TO_FLAG not in output, output)
-
- if SUPPORTS_DEATH_TESTS and not IS_WINDOWS:
- self.assert_(DEATH_TEST_STYLE_FLAG in output, output)
- else:
- self.assert_(DEATH_TEST_STYLE_FLAG not in output, output)
-
- def TestNonHelpFlag(self, flag):
- """Verifies correct behavior when no help flag is specified.
-
- Verifies that when no help flag is specified, the tests are run
- and the help message is not printed.
-
- Args:
- flag: A flag to pass to the binary or None.
- """
-
- exit_code, output = RunWithFlag(flag)
- self.assert_(exit_code != 0)
- self.assert_(not HELP_REGEX.search(output), output)
-
- def testPrintsHelpWithFullFlag(self):
- self.TestHelpFlag('--help')
-
- def testPrintsHelpWithShortFlag(self):
- self.TestHelpFlag('-h')
-
- def testPrintsHelpWithQuestionFlag(self):
- self.TestHelpFlag('-?')
-
- def testPrintsHelpWithWindowsStyleQuestionFlag(self):
- self.TestHelpFlag('/?')
-
- def testPrintsHelpWithUnrecognizedGoogleTestFlag(self):
- self.TestHelpFlag(UNKNOWN_FLAG)
-
- def testPrintsHelpWithIncorrectFlagStyle(self):
- for incorrect_flag in INCORRECT_FLAG_VARIANTS:
- self.TestHelpFlag(incorrect_flag)
-
- def testRunsTestsWithoutHelpFlag(self):
- """Verifies that when no help flag is specified, the tests are run
- and the help message is not printed."""
-
- self.TestNonHelpFlag(None)
-
- def testRunsTestsWithGtestInternalFlag(self):
- """Verifies that the tests are run and no help message is printed when
- a flag starting with Google Test prefix and 'internal_' is supplied."""
-
- self.TestNonHelpFlag(INTERNAL_FLAG_FOR_TESTING)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2009, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This program is meant to be run by gtest_help_test.py. Do not run
-// it directly.
-
-#include "gtest/gtest.h"
-
-// When a help flag is specified, this program should skip the tests
-// and exit with 0; otherwise the following test will be executed,
-// causing this program to exit with a non-zero code.
-TEST(HelpFlagTest, ShouldNotBeRun) {
- ASSERT_TRUE(false) << "Tests shouldn't be run when --help is specified.";
-}
-
-#if GTEST_HAS_DEATH_TEST
-TEST(DeathTest, UsedByPythonScriptToDetectSupportForDeathTestsInThisBinary) {}
-#endif
+++ /dev/null
-# Copyright 2018, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test utilities for gtest_json_output."""
-
-import re
-
-
-def normalize(obj):
- """Normalize output object.
-
- Args:
- obj: Google Test's JSON output object to normalize.
-
- Returns:
- Normalized output without any references to transient information that may
- change from run to run.
- """
- def _normalize(key, value):
- if key == 'time':
- return re.sub(r'^\d+(\.\d+)?s$', '*', value)
- elif key == 'timestamp':
- return re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\dZ$', '*', value)
- elif key == 'failure':
- value = re.sub(r'^.*[/\\](.*:)\d+\n', '\\1*\n', value)
- return re.sub(r'Stack trace:\n(.|\n)*', 'Stack trace:\n*', value)
- else:
- return normalize(value)
- if isinstance(obj, dict):
- return {k: _normalize(k, v) for k, v in obj.items()}
- if isinstance(obj, list):
- return [normalize(x) for x in obj]
- else:
- return obj
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Unit test for Google Test's --gtest_list_tests flag.
-
-A user can ask Google Test to list all tests by specifying the
---gtest_list_tests flag. If output is requested, via --gtest_output=xml
-or --gtest_output=json, the tests are listed, with extra information in the
-output file.
-This script tests such functionality by invoking gtest_list_output_unittest_
- (a program written with Google Test) the command line flags.
-"""
-
-import os
-import re
-import gtest_test_utils
-
-GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
-GTEST_OUTPUT_FLAG = '--gtest_output'
-
-EXPECTED_XML = """<\?xml version="1.0" encoding="UTF-8"\?>
-<testsuites tests="2" name="AllTests">
- <testsuite name="FooTest" tests="2">
- <testcase name="Test1" file=".*gtest_list_output_unittest_.cc" line="43" />
- <testcase name="Test2" file=".*gtest_list_output_unittest_.cc" line="45" />
- </testsuite>
-</testsuites>
-"""
-
-EXPECTED_JSON = """{
- "tests": 2,
- "name": "AllTests",
- "testsuites": \[
- {
- "name": "FooTest",
- "tests": 2,
- "testsuite": \[
- {
- "name": "Test1",
- "file": ".*gtest_list_output_unittest_.cc",
- "line": 43
- },
- {
- "name": "Test2",
- "file": ".*gtest_list_output_unittest_.cc",
- "line": 45
- }
- \]
- }
- \]
-}
-"""
-
-
-class GTestListTestsOutputUnitTest(gtest_test_utils.TestCase):
- """Unit test for Google Test's list tests with output to file functionality.
- """
-
- def testXml(self):
- """Verifies XML output for listing tests in a Google Test binary.
-
- Runs a test program that generates an empty XML output, and
- tests that the XML output is expected.
- """
- self._TestOutput('xml', EXPECTED_XML)
-
- def testJSON(self):
- """Verifies XML output for listing tests in a Google Test binary.
-
- Runs a test program that generates an empty XML output, and
- tests that the XML output is expected.
- """
- self._TestOutput('json', EXPECTED_JSON)
-
- def _GetOutput(self, out_format):
- file_path = os.path.join(gtest_test_utils.GetTempDir(),
- 'test_out.' + out_format)
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
- 'gtest_list_output_unittest_')
-
- command = ([
- gtest_prog_path,
- '%s=%s:%s' % (GTEST_OUTPUT_FLAG, out_format, file_path),
- '--gtest_list_tests'
- ])
- environ_copy = os.environ.copy()
- p = gtest_test_utils.Subprocess(
- command, env=environ_copy, working_dir=gtest_test_utils.GetTempDir())
-
- self.assert_(p.exited)
- self.assertEquals(0, p.exit_code)
- with open(file_path) as f:
- result = f.read()
- return result
-
- def _TestOutput(self, test_format, expected_output):
- actual = self._GetOutput(test_format)
- actual_lines = actual.splitlines()
- expected_lines = expected_output.splitlines()
- line_count = 0
- for actual_line in actual_lines:
- expected_line = expected_lines[line_count]
- expected_line_re = re.compile(expected_line.strip())
- self.assert_(
- expected_line_re.match(actual_line.strip()),
- ('actual output of "%s",\n'
- 'which does not match expected regex of "%s"\n'
- 'on line %d' % (actual, expected_output, line_count)))
- line_count = line_count + 1
-
-
-if __name__ == '__main__':
- os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2018, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: david.schuldenfrei@gmail.com (David Schuldenfrei)
-
-// Unit test for Google Test's --gtest_list_tests and --gtest_output flag.
-//
-// A user can ask Google Test to list all tests that will run,
-// and have the output saved in a Json/Xml file.
-// The tests will not be run after listing.
-//
-// This program will be invoked from a Python unit test.
-// Don't run it directly.
-
-#include "gtest/gtest.h"
-
-TEST(FooTest, Test1) {}
-
-TEST(FooTest, Test2) {}
-
-int main(int argc, char **argv) {
- ::testing::InitGoogleTest(&argc, argv);
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-#include "gtest/gtest.h"
-
-// Tests that we don't have to define main() when we link to
-// gtest_main instead of gtest.
-
-namespace {
-
-TEST(GTestMainTest, ShouldSucceed) {
-}
-
-} // namespace
-
-// We are using the main() function defined in gtest_main.cc, so we
-// don't define it here.
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Tests that a Google Test program that has no test defined can run
-// successfully.
-
-#include "gtest/gtest.h"
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
-
- // An ad-hoc assertion outside of all tests.
- //
- // This serves three purposes:
- //
- // 1. It verifies that an ad-hoc assertion can be executed even if
- // no test is defined.
- // 2. It verifies that a failed ad-hoc assertion causes the test
- // program to fail.
- // 3. We had a bug where the XML output won't be generated if an
- // assertion is executed before RUN_ALL_TESTS() is called, even
- // though --gtest_output=xml is specified. This makes sure the
- // bug is fixed and doesn't regress.
- EXPECT_EQ(1, 2);
-
- // The above EXPECT_EQ() should cause RUN_ALL_TESTS() to return non-zero.
- return RUN_ALL_TESTS() ? 0 : 1;
-}
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file is AUTOMATICALLY GENERATED on 01/02/2019 by command
-// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
-
-// Regression test for gtest_pred_impl.h
-//
-// This file is generated by a script and quite long. If you intend to
-// learn how Google Test works by reading its unit tests, read
-// gtest_unittest.cc instead.
-//
-// This is intended as a regression test for the Google Test predicate
-// assertions. We compile it as part of the gtest_unittest target
-// only to keep the implementation tidy and compact, as it is quite
-// involved to set up the stage for testing Google Test using Google
-// Test itself.
-//
-// Currently, gtest_unittest takes ~11 seconds to run in the testing
-// daemon. In the future, if it grows too large and needs much more
-// time to finish, we should consider separating this file into a
-// stand-alone regression test.
-
-#include <iostream>
-
-#include "gtest/gtest.h"
-#include "gtest/gtest-spi.h"
-
-// A user-defined data type.
-struct Bool {
- explicit Bool(int val) : value(val != 0) {}
-
- bool operator>(int n) const { return value > Bool(n).value; }
-
- Bool operator+(const Bool& rhs) const { return Bool(value + rhs.value); }
-
- bool operator==(const Bool& rhs) const { return value == rhs.value; }
-
- bool value;
-};
-
-// Enables Bool to be used in assertions.
-std::ostream& operator<<(std::ostream& os, const Bool& x) {
- return os << (x.value ? "true" : "false");
-}
-
-// Sample functions/functors for testing unary predicate assertions.
-
-// A unary predicate function.
-template <typename T1>
-bool PredFunction1(T1 v1) {
- return v1 > 0;
-}
-
-// The following two functions are needed to circumvent a bug in
-// gcc 2.95.3, which sometimes has problem with the above template
-// function.
-bool PredFunction1Int(int v1) {
- return v1 > 0;
-}
-bool PredFunction1Bool(Bool v1) {
- return v1 > 0;
-}
-
-// A unary predicate functor.
-struct PredFunctor1 {
- template <typename T1>
- bool operator()(const T1& v1) {
- return v1 > 0;
- }
-};
-
-// A unary predicate-formatter function.
-template <typename T1>
-testing::AssertionResult PredFormatFunction1(const char* e1,
- const T1& v1) {
- if (PredFunction1(v1))
- return testing::AssertionSuccess();
-
- return testing::AssertionFailure()
- << e1
- << " is expected to be positive, but evaluates to "
- << v1 << ".";
-}
-
-// A unary predicate-formatter functor.
-struct PredFormatFunctor1 {
- template <typename T1>
- testing::AssertionResult operator()(const char* e1,
- const T1& v1) const {
- return PredFormatFunction1(e1, v1);
- }
-};
-
-// Tests for {EXPECT|ASSERT}_PRED_FORMAT1.
-
-class Predicate1Test : public testing::Test {
- protected:
- void SetUp() override {
- expected_to_finish_ = true;
- finished_ = false;
- n1_ = 0;
- }
-
- void TearDown() override {
- // Verifies that each of the predicate's arguments was evaluated
- // exactly once.
- EXPECT_EQ(1, n1_) <<
- "The predicate assertion didn't evaluate argument 2 "
- "exactly once.";
-
- // Verifies that the control flow in the test function is expected.
- if (expected_to_finish_ && !finished_) {
- FAIL() << "The predicate assertion unexpactedly aborted the test.";
- } else if (!expected_to_finish_ && finished_) {
- FAIL() << "The failed predicate assertion didn't abort the test "
- "as expected.";
- }
- }
-
- // true if and only if the test function is expected to run to finish.
- static bool expected_to_finish_;
-
- // true if and only if the test function did run to finish.
- static bool finished_;
-
- static int n1_;
-};
-
-bool Predicate1Test::expected_to_finish_;
-bool Predicate1Test::finished_;
-int Predicate1Test::n1_;
-
-typedef Predicate1Test EXPECT_PRED_FORMAT1Test;
-typedef Predicate1Test ASSERT_PRED_FORMAT1Test;
-typedef Predicate1Test EXPECT_PRED1Test;
-typedef Predicate1Test ASSERT_PRED1Test;
-
-// Tests a successful EXPECT_PRED1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED1(PredFunction1Int,
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED1(PredFunction1Bool,
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED1(PredFunctor1(),
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED1(PredFunctor1(),
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED1Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED1(PredFunction1Int,
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED1Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED1(PredFunction1Bool,
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED1Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED1(PredFunctor1(),
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED1Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED1(PredFunctor1(),
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED1(PredFunction1Int,
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED1(PredFunction1Bool,
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED1(PredFunctor1(),
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED1(PredFunctor1(),
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED1Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED1(PredFunction1Int,
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED1Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED1(PredFunction1Bool,
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED1Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED1(PredFunctor1(),
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED1Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED1(PredFunctor1(),
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT1(PredFormatFunction1,
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT1(PredFormatFunction1,
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT1(PredFormatFunction1,
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT1(PredFormatFunction1,
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT1(PredFormatFunctor1(),
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT1(PredFormatFunction1,
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT1(PredFormatFunction1,
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
- ++n1_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
- Bool(++n1_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT1(PredFormatFunction1,
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT1(PredFormatFunction1,
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
- n1_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT1 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT1Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT1(PredFormatFunctor1(),
- Bool(n1_++));
- finished_ = true;
- }, "");
-}
-// Sample functions/functors for testing binary predicate assertions.
-
-// A binary predicate function.
-template <typename T1, typename T2>
-bool PredFunction2(T1 v1, T2 v2) {
- return v1 + v2 > 0;
-}
-
-// The following two functions are needed to circumvent a bug in
-// gcc 2.95.3, which sometimes has problem with the above template
-// function.
-bool PredFunction2Int(int v1, int v2) {
- return v1 + v2 > 0;
-}
-bool PredFunction2Bool(Bool v1, Bool v2) {
- return v1 + v2 > 0;
-}
-
-// A binary predicate functor.
-struct PredFunctor2 {
- template <typename T1, typename T2>
- bool operator()(const T1& v1,
- const T2& v2) {
- return v1 + v2 > 0;
- }
-};
-
-// A binary predicate-formatter function.
-template <typename T1, typename T2>
-testing::AssertionResult PredFormatFunction2(const char* e1,
- const char* e2,
- const T1& v1,
- const T2& v2) {
- if (PredFunction2(v1, v2))
- return testing::AssertionSuccess();
-
- return testing::AssertionFailure()
- << e1 << " + " << e2
- << " is expected to be positive, but evaluates to "
- << v1 + v2 << ".";
-}
-
-// A binary predicate-formatter functor.
-struct PredFormatFunctor2 {
- template <typename T1, typename T2>
- testing::AssertionResult operator()(const char* e1,
- const char* e2,
- const T1& v1,
- const T2& v2) const {
- return PredFormatFunction2(e1, e2, v1, v2);
- }
-};
-
-// Tests for {EXPECT|ASSERT}_PRED_FORMAT2.
-
-class Predicate2Test : public testing::Test {
- protected:
- void SetUp() override {
- expected_to_finish_ = true;
- finished_ = false;
- n1_ = n2_ = 0;
- }
-
- void TearDown() override {
- // Verifies that each of the predicate's arguments was evaluated
- // exactly once.
- EXPECT_EQ(1, n1_) <<
- "The predicate assertion didn't evaluate argument 2 "
- "exactly once.";
- EXPECT_EQ(1, n2_) <<
- "The predicate assertion didn't evaluate argument 3 "
- "exactly once.";
-
- // Verifies that the control flow in the test function is expected.
- if (expected_to_finish_ && !finished_) {
- FAIL() << "The predicate assertion unexpactedly aborted the test.";
- } else if (!expected_to_finish_ && finished_) {
- FAIL() << "The failed predicate assertion didn't abort the test "
- "as expected.";
- }
- }
-
- // true if and only if the test function is expected to run to finish.
- static bool expected_to_finish_;
-
- // true if and only if the test function did run to finish.
- static bool finished_;
-
- static int n1_;
- static int n2_;
-};
-
-bool Predicate2Test::expected_to_finish_;
-bool Predicate2Test::finished_;
-int Predicate2Test::n1_;
-int Predicate2Test::n2_;
-
-typedef Predicate2Test EXPECT_PRED_FORMAT2Test;
-typedef Predicate2Test ASSERT_PRED_FORMAT2Test;
-typedef Predicate2Test EXPECT_PRED2Test;
-typedef Predicate2Test ASSERT_PRED2Test;
-
-// Tests a successful EXPECT_PRED2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED2(PredFunction2Int,
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED2(PredFunction2Bool,
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED2(PredFunctor2(),
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED2(PredFunctor2(),
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED2Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED2(PredFunction2Int,
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED2Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED2(PredFunction2Bool,
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED2Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED2(PredFunctor2(),
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED2Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED2(PredFunctor2(),
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED2(PredFunction2Int,
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED2(PredFunction2Bool,
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED2(PredFunctor2(),
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED2(PredFunctor2(),
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED2Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED2(PredFunction2Int,
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED2Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED2(PredFunction2Bool,
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED2Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED2(PredFunctor2(),
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED2Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED2(PredFunctor2(),
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT2(PredFormatFunction2,
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT2(PredFormatFunction2,
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(PredFormatFunction2,
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(PredFormatFunction2,
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(PredFormatFunctor2(),
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT2(PredFormatFunction2,
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT2(PredFormatFunction2,
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
- ++n1_,
- ++n2_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
- Bool(++n1_),
- Bool(++n2_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT2(PredFormatFunction2,
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT2(PredFormatFunction2,
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
- n1_++,
- n2_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT2 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT2Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT2(PredFormatFunctor2(),
- Bool(n1_++),
- Bool(n2_++));
- finished_ = true;
- }, "");
-}
-// Sample functions/functors for testing ternary predicate assertions.
-
-// A ternary predicate function.
-template <typename T1, typename T2, typename T3>
-bool PredFunction3(T1 v1, T2 v2, T3 v3) {
- return v1 + v2 + v3 > 0;
-}
-
-// The following two functions are needed to circumvent a bug in
-// gcc 2.95.3, which sometimes has problem with the above template
-// function.
-bool PredFunction3Int(int v1, int v2, int v3) {
- return v1 + v2 + v3 > 0;
-}
-bool PredFunction3Bool(Bool v1, Bool v2, Bool v3) {
- return v1 + v2 + v3 > 0;
-}
-
-// A ternary predicate functor.
-struct PredFunctor3 {
- template <typename T1, typename T2, typename T3>
- bool operator()(const T1& v1,
- const T2& v2,
- const T3& v3) {
- return v1 + v2 + v3 > 0;
- }
-};
-
-// A ternary predicate-formatter function.
-template <typename T1, typename T2, typename T3>
-testing::AssertionResult PredFormatFunction3(const char* e1,
- const char* e2,
- const char* e3,
- const T1& v1,
- const T2& v2,
- const T3& v3) {
- if (PredFunction3(v1, v2, v3))
- return testing::AssertionSuccess();
-
- return testing::AssertionFailure()
- << e1 << " + " << e2 << " + " << e3
- << " is expected to be positive, but evaluates to "
- << v1 + v2 + v3 << ".";
-}
-
-// A ternary predicate-formatter functor.
-struct PredFormatFunctor3 {
- template <typename T1, typename T2, typename T3>
- testing::AssertionResult operator()(const char* e1,
- const char* e2,
- const char* e3,
- const T1& v1,
- const T2& v2,
- const T3& v3) const {
- return PredFormatFunction3(e1, e2, e3, v1, v2, v3);
- }
-};
-
-// Tests for {EXPECT|ASSERT}_PRED_FORMAT3.
-
-class Predicate3Test : public testing::Test {
- protected:
- void SetUp() override {
- expected_to_finish_ = true;
- finished_ = false;
- n1_ = n2_ = n3_ = 0;
- }
-
- void TearDown() override {
- // Verifies that each of the predicate's arguments was evaluated
- // exactly once.
- EXPECT_EQ(1, n1_) <<
- "The predicate assertion didn't evaluate argument 2 "
- "exactly once.";
- EXPECT_EQ(1, n2_) <<
- "The predicate assertion didn't evaluate argument 3 "
- "exactly once.";
- EXPECT_EQ(1, n3_) <<
- "The predicate assertion didn't evaluate argument 4 "
- "exactly once.";
-
- // Verifies that the control flow in the test function is expected.
- if (expected_to_finish_ && !finished_) {
- FAIL() << "The predicate assertion unexpactedly aborted the test.";
- } else if (!expected_to_finish_ && finished_) {
- FAIL() << "The failed predicate assertion didn't abort the test "
- "as expected.";
- }
- }
-
- // true if and only if the test function is expected to run to finish.
- static bool expected_to_finish_;
-
- // true if and only if the test function did run to finish.
- static bool finished_;
-
- static int n1_;
- static int n2_;
- static int n3_;
-};
-
-bool Predicate3Test::expected_to_finish_;
-bool Predicate3Test::finished_;
-int Predicate3Test::n1_;
-int Predicate3Test::n2_;
-int Predicate3Test::n3_;
-
-typedef Predicate3Test EXPECT_PRED_FORMAT3Test;
-typedef Predicate3Test ASSERT_PRED_FORMAT3Test;
-typedef Predicate3Test EXPECT_PRED3Test;
-typedef Predicate3Test ASSERT_PRED3Test;
-
-// Tests a successful EXPECT_PRED3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED3(PredFunction3Int,
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED3(PredFunction3Bool,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED3(PredFunctor3(),
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED3(PredFunctor3(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED3Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED3(PredFunction3Int,
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED3Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED3(PredFunction3Bool,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED3Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED3(PredFunctor3(),
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED3Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED3(PredFunctor3(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED3(PredFunction3Int,
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED3(PredFunction3Bool,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED3(PredFunctor3(),
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED3(PredFunctor3(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED3Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED3(PredFunction3Int,
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED3Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED3(PredFunction3Bool,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED3Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED3(PredFunctor3(),
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED3Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED3(PredFunctor3(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT3(PredFormatFunction3,
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT3(PredFormatFunction3,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT3(PredFormatFunction3,
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT3(PredFormatFunction3,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT3(PredFormatFunctor3(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT3(PredFormatFunction3,
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT3(PredFormatFunction3,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
- ++n1_,
- ++n2_,
- ++n3_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT3(PredFormatFunction3,
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT3(PredFormatFunction3,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
- n1_++,
- n2_++,
- n3_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT3 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT3Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT3(PredFormatFunctor3(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++));
- finished_ = true;
- }, "");
-}
-// Sample functions/functors for testing 4-ary predicate assertions.
-
-// A 4-ary predicate function.
-template <typename T1, typename T2, typename T3, typename T4>
-bool PredFunction4(T1 v1, T2 v2, T3 v3, T4 v4) {
- return v1 + v2 + v3 + v4 > 0;
-}
-
-// The following two functions are needed to circumvent a bug in
-// gcc 2.95.3, which sometimes has problem with the above template
-// function.
-bool PredFunction4Int(int v1, int v2, int v3, int v4) {
- return v1 + v2 + v3 + v4 > 0;
-}
-bool PredFunction4Bool(Bool v1, Bool v2, Bool v3, Bool v4) {
- return v1 + v2 + v3 + v4 > 0;
-}
-
-// A 4-ary predicate functor.
-struct PredFunctor4 {
- template <typename T1, typename T2, typename T3, typename T4>
- bool operator()(const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4) {
- return v1 + v2 + v3 + v4 > 0;
- }
-};
-
-// A 4-ary predicate-formatter function.
-template <typename T1, typename T2, typename T3, typename T4>
-testing::AssertionResult PredFormatFunction4(const char* e1,
- const char* e2,
- const char* e3,
- const char* e4,
- const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4) {
- if (PredFunction4(v1, v2, v3, v4))
- return testing::AssertionSuccess();
-
- return testing::AssertionFailure()
- << e1 << " + " << e2 << " + " << e3 << " + " << e4
- << " is expected to be positive, but evaluates to "
- << v1 + v2 + v3 + v4 << ".";
-}
-
-// A 4-ary predicate-formatter functor.
-struct PredFormatFunctor4 {
- template <typename T1, typename T2, typename T3, typename T4>
- testing::AssertionResult operator()(const char* e1,
- const char* e2,
- const char* e3,
- const char* e4,
- const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4) const {
- return PredFormatFunction4(e1, e2, e3, e4, v1, v2, v3, v4);
- }
-};
-
-// Tests for {EXPECT|ASSERT}_PRED_FORMAT4.
-
-class Predicate4Test : public testing::Test {
- protected:
- void SetUp() override {
- expected_to_finish_ = true;
- finished_ = false;
- n1_ = n2_ = n3_ = n4_ = 0;
- }
-
- void TearDown() override {
- // Verifies that each of the predicate's arguments was evaluated
- // exactly once.
- EXPECT_EQ(1, n1_) <<
- "The predicate assertion didn't evaluate argument 2 "
- "exactly once.";
- EXPECT_EQ(1, n2_) <<
- "The predicate assertion didn't evaluate argument 3 "
- "exactly once.";
- EXPECT_EQ(1, n3_) <<
- "The predicate assertion didn't evaluate argument 4 "
- "exactly once.";
- EXPECT_EQ(1, n4_) <<
- "The predicate assertion didn't evaluate argument 5 "
- "exactly once.";
-
- // Verifies that the control flow in the test function is expected.
- if (expected_to_finish_ && !finished_) {
- FAIL() << "The predicate assertion unexpactedly aborted the test.";
- } else if (!expected_to_finish_ && finished_) {
- FAIL() << "The failed predicate assertion didn't abort the test "
- "as expected.";
- }
- }
-
- // true if and only if the test function is expected to run to finish.
- static bool expected_to_finish_;
-
- // true if and only if the test function did run to finish.
- static bool finished_;
-
- static int n1_;
- static int n2_;
- static int n3_;
- static int n4_;
-};
-
-bool Predicate4Test::expected_to_finish_;
-bool Predicate4Test::finished_;
-int Predicate4Test::n1_;
-int Predicate4Test::n2_;
-int Predicate4Test::n3_;
-int Predicate4Test::n4_;
-
-typedef Predicate4Test EXPECT_PRED_FORMAT4Test;
-typedef Predicate4Test ASSERT_PRED_FORMAT4Test;
-typedef Predicate4Test EXPECT_PRED4Test;
-typedef Predicate4Test ASSERT_PRED4Test;
-
-// Tests a successful EXPECT_PRED4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED4(PredFunction4Int,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED4(PredFunction4Bool,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED4(PredFunctor4(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED4(PredFunctor4(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED4Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED4(PredFunction4Int,
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED4Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED4(PredFunction4Bool,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED4Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED4(PredFunctor4(),
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED4Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED4(PredFunctor4(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED4(PredFunction4Int,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED4(PredFunction4Bool,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED4(PredFunctor4(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED4(PredFunctor4(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED4Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED4(PredFunction4Int,
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED4Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED4(PredFunction4Bool,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED4Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED4(PredFunctor4(),
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED4Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED4(PredFunctor4(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT4(PredFormatFunction4,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT4(PredFormatFunction4,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT4(PredFormatFunction4,
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT4(PredFormatFunction4,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT4(PredFormatFunctor4(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT4(PredFormatFunction4,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT4(PredFormatFunction4,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT4(PredFormatFunction4,
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT4(PredFormatFunction4,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
- n1_++,
- n2_++,
- n3_++,
- n4_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT4 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT4Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT4(PredFormatFunctor4(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++));
- finished_ = true;
- }, "");
-}
-// Sample functions/functors for testing 5-ary predicate assertions.
-
-// A 5-ary predicate function.
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-bool PredFunction5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) {
- return v1 + v2 + v3 + v4 + v5 > 0;
-}
-
-// The following two functions are needed to circumvent a bug in
-// gcc 2.95.3, which sometimes has problem with the above template
-// function.
-bool PredFunction5Int(int v1, int v2, int v3, int v4, int v5) {
- return v1 + v2 + v3 + v4 + v5 > 0;
-}
-bool PredFunction5Bool(Bool v1, Bool v2, Bool v3, Bool v4, Bool v5) {
- return v1 + v2 + v3 + v4 + v5 > 0;
-}
-
-// A 5-ary predicate functor.
-struct PredFunctor5 {
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
- bool operator()(const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4,
- const T5& v5) {
- return v1 + v2 + v3 + v4 + v5 > 0;
- }
-};
-
-// A 5-ary predicate-formatter function.
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-testing::AssertionResult PredFormatFunction5(const char* e1,
- const char* e2,
- const char* e3,
- const char* e4,
- const char* e5,
- const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4,
- const T5& v5) {
- if (PredFunction5(v1, v2, v3, v4, v5))
- return testing::AssertionSuccess();
-
- return testing::AssertionFailure()
- << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
- << " is expected to be positive, but evaluates to "
- << v1 + v2 + v3 + v4 + v5 << ".";
-}
-
-// A 5-ary predicate-formatter functor.
-struct PredFormatFunctor5 {
- template <typename T1, typename T2, typename T3, typename T4, typename T5>
- testing::AssertionResult operator()(const char* e1,
- const char* e2,
- const char* e3,
- const char* e4,
- const char* e5,
- const T1& v1,
- const T2& v2,
- const T3& v3,
- const T4& v4,
- const T5& v5) const {
- return PredFormatFunction5(e1, e2, e3, e4, e5, v1, v2, v3, v4, v5);
- }
-};
-
-// Tests for {EXPECT|ASSERT}_PRED_FORMAT5.
-
-class Predicate5Test : public testing::Test {
- protected:
- void SetUp() override {
- expected_to_finish_ = true;
- finished_ = false;
- n1_ = n2_ = n3_ = n4_ = n5_ = 0;
- }
-
- void TearDown() override {
- // Verifies that each of the predicate's arguments was evaluated
- // exactly once.
- EXPECT_EQ(1, n1_) <<
- "The predicate assertion didn't evaluate argument 2 "
- "exactly once.";
- EXPECT_EQ(1, n2_) <<
- "The predicate assertion didn't evaluate argument 3 "
- "exactly once.";
- EXPECT_EQ(1, n3_) <<
- "The predicate assertion didn't evaluate argument 4 "
- "exactly once.";
- EXPECT_EQ(1, n4_) <<
- "The predicate assertion didn't evaluate argument 5 "
- "exactly once.";
- EXPECT_EQ(1, n5_) <<
- "The predicate assertion didn't evaluate argument 6 "
- "exactly once.";
-
- // Verifies that the control flow in the test function is expected.
- if (expected_to_finish_ && !finished_) {
- FAIL() << "The predicate assertion unexpactedly aborted the test.";
- } else if (!expected_to_finish_ && finished_) {
- FAIL() << "The failed predicate assertion didn't abort the test "
- "as expected.";
- }
- }
-
- // true if and only if the test function is expected to run to finish.
- static bool expected_to_finish_;
-
- // true if and only if the test function did run to finish.
- static bool finished_;
-
- static int n1_;
- static int n2_;
- static int n3_;
- static int n4_;
- static int n5_;
-};
-
-bool Predicate5Test::expected_to_finish_;
-bool Predicate5Test::finished_;
-int Predicate5Test::n1_;
-int Predicate5Test::n2_;
-int Predicate5Test::n3_;
-int Predicate5Test::n4_;
-int Predicate5Test::n5_;
-
-typedef Predicate5Test EXPECT_PRED_FORMAT5Test;
-typedef Predicate5Test ASSERT_PRED_FORMAT5Test;
-typedef Predicate5Test EXPECT_PRED5Test;
-typedef Predicate5Test ASSERT_PRED5Test;
-
-// Tests a successful EXPECT_PRED5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED5(PredFunction5Int,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED5(PredFunction5Bool,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED5(PredFunctor5(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED5(PredFunctor5(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED5Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED5(PredFunction5Int,
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED5Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED5(PredFunction5Bool,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED5Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED5(PredFunctor5(),
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED5Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED5(PredFunctor5(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED5(PredFunction5Int,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED5(PredFunction5Bool,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED5(PredFunctor5(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED5(PredFunctor5(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED5Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED5(PredFunction5Int,
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED5Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED5(PredFunction5Bool,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED5Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED5(PredFunctor5(),
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED5Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED5(PredFunctor5(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT5(PredFormatFunction5,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT5(PredFormatFunction5,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
- EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
- EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a failed EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT5(PredFormatFunction5,
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT5(PredFormatFunction5,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed EXPECT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(EXPECT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT5(PredFormatFunctor5(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a successful ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT5(PredFormatFunction5,
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT5(PredFormatFunction5,
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeSuccess) {
- ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
- ++n1_,
- ++n2_,
- ++n3_,
- ++n4_,
- ++n5_);
- finished_ = true;
-}
-
-// Tests a successful ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeSuccess) {
- ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
- Bool(++n1_),
- Bool(++n2_),
- Bool(++n3_),
- Bool(++n4_),
- Bool(++n5_));
- finished_ = true;
-}
-
-// Tests a failed ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT5(PredFormatFunction5,
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a function on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctionOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT5(PredFormatFunction5,
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a built-in type (int).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnBuiltInTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
- n1_++,
- n2_++,
- n3_++,
- n4_++,
- n5_++);
- finished_ = true;
- }, "");
-}
-
-// Tests a failed ASSERT_PRED_FORMAT5 where the
-// predicate-formatter is a functor on a user-defined type (Bool).
-TEST_F(ASSERT_PRED_FORMAT5Test, FunctorOnUserTypeFailure) {
- expected_to_finish_ = false;
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT5(PredFormatFunctor5(),
- Bool(n1_++),
- Bool(n2_++),
- Bool(n3_++),
- Bool(n4_++),
- Bool(n5_++));
- finished_ = true;
- }, "");
-}
+++ /dev/null
-// Copyright 2013, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests that Google Test manipulates the premature-exit-detection
-// file correctly.
-
-#include <stdio.h>
-
-#include "gtest/gtest.h"
-
-using ::testing::InitGoogleTest;
-using ::testing::Test;
-using ::testing::internal::posix::GetEnv;
-using ::testing::internal::posix::Stat;
-using ::testing::internal::posix::StatStruct;
-
-namespace {
-
-class PrematureExitTest : public Test {
- public:
- // Returns true if and only if the given file exists.
- static bool FileExists(const char* filepath) {
- StatStruct stat;
- return Stat(filepath, &stat) == 0;
- }
-
- protected:
- PrematureExitTest() {
- premature_exit_file_path_ = GetEnv("TEST_PREMATURE_EXIT_FILE");
-
- // Normalize NULL to "" for ease of handling.
- if (premature_exit_file_path_ == nullptr) {
- premature_exit_file_path_ = "";
- }
- }
-
- // Returns true if and only if the premature-exit file exists.
- bool PrematureExitFileExists() const {
- return FileExists(premature_exit_file_path_);
- }
-
- const char* premature_exit_file_path_;
-};
-
-typedef PrematureExitTest PrematureExitDeathTest;
-
-// Tests that:
-// - the premature-exit file exists during the execution of a
-// death test (EXPECT_DEATH*), and
-// - a death test doesn't interfere with the main test process's
-// handling of the premature-exit file.
-TEST_F(PrematureExitDeathTest, FileExistsDuringExecutionOfDeathTest) {
- if (*premature_exit_file_path_ == '\0') {
- return;
- }
-
- EXPECT_DEATH_IF_SUPPORTED({
- // If the file exists, crash the process such that the main test
- // process will catch the (expected) crash and report a success;
- // otherwise don't crash, which will cause the main test process
- // to report that the death test has failed.
- if (PrematureExitFileExists()) {
- exit(1);
- }
- }, "");
-}
-
-// Tests that the premature-exit file exists during the execution of a
-// normal (non-death) test.
-TEST_F(PrematureExitTest, PrematureExitFileExistsDuringTestExecution) {
- if (*premature_exit_file_path_ == '\0') {
- return;
- }
-
- EXPECT_TRUE(PrematureExitFileExists())
- << " file " << premature_exit_file_path_
- << " should exist during test execution, but doesn't.";
-}
-
-} // namespace
-
-int main(int argc, char **argv) {
- InitGoogleTest(&argc, argv);
- const int exit_code = RUN_ALL_TESTS();
-
- // Test that the premature-exit file is deleted upon return from
- // RUN_ALL_TESTS().
- const char* const filepath = GetEnv("TEST_PREMATURE_EXIT_FILE");
- if (filepath != nullptr && *filepath != '\0') {
- if (PrematureExitTest::FileExists(filepath)) {
- printf(
- "File %s shouldn't exist after the test program finishes, but does.",
- filepath);
- return 1;
- }
- }
-
- return exit_code;
-}
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Unit test for gtest_prod.h.
-
-#include "production.h"
-#include "gtest/gtest.h"
-
-// Tests that private members can be accessed from a TEST declared as
-// a friend of the class.
-TEST(PrivateCodeTest, CanAccessPrivateMembers) {
- PrivateCode a;
- EXPECT_EQ(0, a.x_);
-
- a.set_x(1);
- EXPECT_EQ(1, a.x_);
-}
-
-typedef testing::Test PrivateCodeFixtureTest;
-
-// Tests that private members can be accessed from a TEST_F declared
-// as a friend of the class.
-TEST_F(PrivateCodeFixtureTest, CanAccessPrivateMembers) {
- PrivateCode a;
- EXPECT_EQ(0, a.x_);
-
- a.set_x(2);
- EXPECT_EQ(2, a.x_);
-}
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Tests the --gtest_repeat=number flag.
-
-#include <stdlib.h>
-#include <iostream>
-#include "gtest/gtest.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-
-GTEST_DECLARE_string_(death_test_style);
-GTEST_DECLARE_string_(filter);
-GTEST_DECLARE_int32_(repeat);
-
-} // namespace testing
-
-using testing::GTEST_FLAG(death_test_style);
-using testing::GTEST_FLAG(filter);
-using testing::GTEST_FLAG(repeat);
-
-namespace {
-
-// We need this when we are testing Google Test itself and therefore
-// cannot use Google Test assertions.
-#define GTEST_CHECK_INT_EQ_(expected, actual) \
- do {\
- const int expected_val = (expected);\
- const int actual_val = (actual);\
- if (::testing::internal::IsTrue(expected_val != actual_val)) {\
- ::std::cout << "Value of: " #actual "\n"\
- << " Actual: " << actual_val << "\n"\
- << "Expected: " #expected "\n"\
- << "Which is: " << expected_val << "\n";\
- ::testing::internal::posix::Abort();\
- }\
- } while (::testing::internal::AlwaysFalse())
-
-
-// Used for verifying that global environment set-up and tear-down are
-// inside the --gtest_repeat loop.
-
-int g_environment_set_up_count = 0;
-int g_environment_tear_down_count = 0;
-
-class MyEnvironment : public testing::Environment {
- public:
- MyEnvironment() {}
- void SetUp() override { g_environment_set_up_count++; }
- void TearDown() override { g_environment_tear_down_count++; }
-};
-
-// A test that should fail.
-
-int g_should_fail_count = 0;
-
-TEST(FooTest, ShouldFail) {
- g_should_fail_count++;
- EXPECT_EQ(0, 1) << "Expected failure.";
-}
-
-// A test that should pass.
-
-int g_should_pass_count = 0;
-
-TEST(FooTest, ShouldPass) {
- g_should_pass_count++;
-}
-
-// A test that contains a thread-safe death test and a fast death
-// test. It should pass.
-
-int g_death_test_count = 0;
-
-TEST(BarDeathTest, ThreadSafeAndFast) {
- g_death_test_count++;
-
- GTEST_FLAG(death_test_style) = "threadsafe";
- EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
-
- GTEST_FLAG(death_test_style) = "fast";
- EXPECT_DEATH_IF_SUPPORTED(::testing::internal::posix::Abort(), "");
-}
-
-int g_param_test_count = 0;
-
-const int kNumberOfParamTests = 10;
-
-class MyParamTest : public testing::TestWithParam<int> {};
-
-TEST_P(MyParamTest, ShouldPass) {
- GTEST_CHECK_INT_EQ_(g_param_test_count % kNumberOfParamTests, GetParam());
- g_param_test_count++;
-}
-INSTANTIATE_TEST_SUITE_P(MyParamSequence,
- MyParamTest,
- testing::Range(0, kNumberOfParamTests));
-
-// Resets the count for each test.
-void ResetCounts() {
- g_environment_set_up_count = 0;
- g_environment_tear_down_count = 0;
- g_should_fail_count = 0;
- g_should_pass_count = 0;
- g_death_test_count = 0;
- g_param_test_count = 0;
-}
-
-// Checks that the count for each test is expected.
-void CheckCounts(int expected) {
- GTEST_CHECK_INT_EQ_(expected, g_environment_set_up_count);
- GTEST_CHECK_INT_EQ_(expected, g_environment_tear_down_count);
- GTEST_CHECK_INT_EQ_(expected, g_should_fail_count);
- GTEST_CHECK_INT_EQ_(expected, g_should_pass_count);
- GTEST_CHECK_INT_EQ_(expected, g_death_test_count);
- GTEST_CHECK_INT_EQ_(expected * kNumberOfParamTests, g_param_test_count);
-}
-
-// Tests the behavior of Google Test when --gtest_repeat is not specified.
-void TestRepeatUnspecified() {
- ResetCounts();
- GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
- CheckCounts(1);
-}
-
-// Tests the behavior of Google Test when --gtest_repeat has the given value.
-void TestRepeat(int repeat) {
- GTEST_FLAG(repeat) = repeat;
-
- ResetCounts();
- GTEST_CHECK_INT_EQ_(repeat > 0 ? 1 : 0, RUN_ALL_TESTS());
- CheckCounts(repeat);
-}
-
-// Tests using --gtest_repeat when --gtest_filter specifies an empty
-// set of tests.
-void TestRepeatWithEmptyFilter(int repeat) {
- GTEST_FLAG(repeat) = repeat;
- GTEST_FLAG(filter) = "None";
-
- ResetCounts();
- GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
- CheckCounts(0);
-}
-
-// Tests using --gtest_repeat when --gtest_filter specifies a set of
-// successful tests.
-void TestRepeatWithFilterForSuccessfulTests(int repeat) {
- GTEST_FLAG(repeat) = repeat;
- GTEST_FLAG(filter) = "*-*ShouldFail";
-
- ResetCounts();
- GTEST_CHECK_INT_EQ_(0, RUN_ALL_TESTS());
- GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
- GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
- GTEST_CHECK_INT_EQ_(0, g_should_fail_count);
- GTEST_CHECK_INT_EQ_(repeat, g_should_pass_count);
- GTEST_CHECK_INT_EQ_(repeat, g_death_test_count);
- GTEST_CHECK_INT_EQ_(repeat * kNumberOfParamTests, g_param_test_count);
-}
-
-// Tests using --gtest_repeat when --gtest_filter specifies a set of
-// failed tests.
-void TestRepeatWithFilterForFailedTests(int repeat) {
- GTEST_FLAG(repeat) = repeat;
- GTEST_FLAG(filter) = "*ShouldFail";
-
- ResetCounts();
- GTEST_CHECK_INT_EQ_(1, RUN_ALL_TESTS());
- GTEST_CHECK_INT_EQ_(repeat, g_environment_set_up_count);
- GTEST_CHECK_INT_EQ_(repeat, g_environment_tear_down_count);
- GTEST_CHECK_INT_EQ_(repeat, g_should_fail_count);
- GTEST_CHECK_INT_EQ_(0, g_should_pass_count);
- GTEST_CHECK_INT_EQ_(0, g_death_test_count);
- GTEST_CHECK_INT_EQ_(0, g_param_test_count);
-}
-
-} // namespace
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
-
- testing::AddGlobalTestEnvironment(new MyEnvironment);
-
- TestRepeatUnspecified();
- TestRepeat(0);
- TestRepeat(1);
- TestRepeat(5);
-
- TestRepeatWithEmptyFilter(2);
- TestRepeatWithEmptyFilter(3);
-
- TestRepeatWithFilterForSuccessfulTests(3);
-
- TestRepeatWithFilterForFailedTests(4);
-
- // It would be nice to verify that the tests indeed loop forever
- // when GTEST_FLAG(repeat) is negative, but this test will be quite
- // complicated to write. Since this flag is for interactive
- // debugging only and doesn't affect the normal test result, such a
- // test would be an overkill.
-
- printf("PASS\n");
- return 0;
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2019 Google LLC. All Rights Reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Tests Google Test's gtest skip in environment setup behavior.
-
-This script invokes gtest_skip_in_environment_setup_test_ and verifies its
-output.
-"""
-
-import gtest_test_utils
-
-# Path to the gtest_skip_in_environment_setup_test binary
-EXE_PATH = gtest_test_utils.GetTestExecutablePath(
- 'gtest_skip_in_environment_setup_test')
-
-OUTPUT = gtest_test_utils.Subprocess([EXE_PATH]).output
-
-
-# Test.
-class SkipEntireEnvironmentTest(gtest_test_utils.TestCase):
-
- def testSkipEntireEnvironmentTest(self):
- self.assertIn('Skipping the entire environment', OUTPUT)
- self.assertNotIn('FAILED', OUTPUT)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2019, Google LLC.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google LLC. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// This test verifies that skipping in the environment results in the
-// testcases being skipped.
-
-#include <iostream>
-#include "gtest/gtest.h"
-
-class SetupEnvironment : public testing::Environment {
- public:
- void SetUp() override { GTEST_SKIP() << "Skipping the entire environment"; }
-};
-
-TEST(Test, AlwaysFails) { EXPECT_EQ(true, false); }
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
-
- testing::AddGlobalTestEnvironment(new SetupEnvironment());
-
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-// Copyright 2008 Google Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Author: arseny.aprelev@gmail.com (Arseny Aprelev)
-//
-
-#include "gtest/gtest.h"
-
-using ::testing::Test;
-
-TEST(SkipTest, DoesSkip) {
- GTEST_SKIP();
- EXPECT_EQ(0, 1);
-}
-
-class Fixture : public Test {
- protected:
- void SetUp() override {
- GTEST_SKIP() << "skipping all tests for this fixture";
- }
-};
-
-TEST_F(Fixture, SkipsOneTest) {
- EXPECT_EQ(5, 7);
-}
-
-TEST_F(Fixture, SkipsAnotherTest) {
- EXPECT_EQ(99, 100);
-}
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// This test verifies that it's possible to use Google Test by including
-// the gtest.h header file alone.
-
-#include "gtest/gtest.h"
-
-namespace {
-
-void Subroutine() {
- EXPECT_EQ(42, 42);
-}
-
-TEST(NoFatalFailureTest, ExpectNoFatalFailure) {
- EXPECT_NO_FATAL_FAILURE(;);
- EXPECT_NO_FATAL_FAILURE(SUCCEED());
- EXPECT_NO_FATAL_FAILURE(Subroutine());
- EXPECT_NO_FATAL_FAILURE({ SUCCEED(); });
-}
-
-TEST(NoFatalFailureTest, AssertNoFatalFailure) {
- ASSERT_NO_FATAL_FAILURE(;);
- ASSERT_NO_FATAL_FAILURE(SUCCEED());
- ASSERT_NO_FATAL_FAILURE(Subroutine());
- ASSERT_NO_FATAL_FAILURE({ SUCCEED(); });
-}
-
-} // namespace
+++ /dev/null
-// Copyright 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Tests that SCOPED_TRACE() and various Google Test assertions can be
-// used in a large number of threads concurrently.
-
-#include "gtest/gtest.h"
-
-#include <vector>
-
-#include "src/gtest-internal-inl.h"
-
-#if GTEST_IS_THREADSAFE
-
-namespace testing {
-namespace {
-
-using internal::Notification;
-using internal::TestPropertyKeyIs;
-using internal::ThreadWithParam;
-
-// In order to run tests in this file, for platforms where Google Test is
-// thread safe, implement ThreadWithParam. See the description of its API
-// in gtest-port.h, where it is defined for already supported platforms.
-
-// How many threads to create?
-const int kThreadCount = 50;
-
-std::string IdToKey(int id, const char* suffix) {
- Message key;
- key << "key_" << id << "_" << suffix;
- return key.GetString();
-}
-
-std::string IdToString(int id) {
- Message id_message;
- id_message << id;
- return id_message.GetString();
-}
-
-void ExpectKeyAndValueWereRecordedForId(
- const std::vector<TestProperty>& properties,
- int id, const char* suffix) {
- TestPropertyKeyIs matches_key(IdToKey(id, suffix).c_str());
- const std::vector<TestProperty>::const_iterator property =
- std::find_if(properties.begin(), properties.end(), matches_key);
- ASSERT_TRUE(property != properties.end())
- << "expecting " << suffix << " value for id " << id;
- EXPECT_STREQ(IdToString(id).c_str(), property->value());
-}
-
-// Calls a large number of Google Test assertions, where exactly one of them
-// will fail.
-void ManyAsserts(int id) {
- GTEST_LOG_(INFO) << "Thread #" << id << " running...";
-
- SCOPED_TRACE(Message() << "Thread #" << id);
-
- for (int i = 0; i < kThreadCount; i++) {
- SCOPED_TRACE(Message() << "Iteration #" << i);
-
- // A bunch of assertions that should succeed.
- EXPECT_TRUE(true);
- ASSERT_FALSE(false) << "This shouldn't fail.";
- EXPECT_STREQ("a", "a");
- ASSERT_LE(5, 6);
- EXPECT_EQ(i, i) << "This shouldn't fail.";
-
- // RecordProperty() should interact safely with other threads as well.
- // The shared_key forces property updates.
- Test::RecordProperty(IdToKey(id, "string").c_str(), IdToString(id).c_str());
- Test::RecordProperty(IdToKey(id, "int").c_str(), id);
- Test::RecordProperty("shared_key", IdToString(id).c_str());
-
- // This assertion should fail kThreadCount times per thread. It
- // is for testing whether Google Test can handle failed assertions in a
- // multi-threaded context.
- EXPECT_LT(i, 0) << "This should always fail.";
- }
-}
-
-void CheckTestFailureCount(int expected_failures) {
- const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
- const TestResult* const result = info->result();
- GTEST_CHECK_(expected_failures == result->total_part_count())
- << "Logged " << result->total_part_count() << " failures "
- << " vs. " << expected_failures << " expected";
-}
-
-// Tests using SCOPED_TRACE() and Google Test assertions in many threads
-// concurrently.
-TEST(StressTest, CanUseScopedTraceAndAssertionsInManyThreads) {
- {
- std::unique_ptr<ThreadWithParam<int> > threads[kThreadCount];
- Notification threads_can_start;
- for (int i = 0; i != kThreadCount; i++)
- threads[i].reset(new ThreadWithParam<int>(&ManyAsserts,
- i,
- &threads_can_start));
-
- threads_can_start.Notify();
-
- // Blocks until all the threads are done.
- for (int i = 0; i != kThreadCount; i++)
- threads[i]->Join();
- }
-
- // Ensures that kThreadCount*kThreadCount failures have been reported.
- const TestInfo* const info = UnitTest::GetInstance()->current_test_info();
- const TestResult* const result = info->result();
-
- std::vector<TestProperty> properties;
- // We have no access to the TestResult's list of properties but we can
- // copy them one by one.
- for (int i = 0; i < result->test_property_count(); ++i)
- properties.push_back(result->GetTestProperty(i));
-
- EXPECT_EQ(kThreadCount * 2 + 1, result->test_property_count())
- << "String and int values recorded on each thread, "
- << "as well as one shared_key";
- for (int i = 0; i < kThreadCount; ++i) {
- ExpectKeyAndValueWereRecordedForId(properties, i, "string");
- ExpectKeyAndValueWereRecordedForId(properties, i, "int");
- }
- CheckTestFailureCount(kThreadCount*kThreadCount);
-}
-
-void FailingThread(bool is_fatal) {
- if (is_fatal)
- FAIL() << "Fatal failure in some other thread. "
- << "(This failure is expected.)";
- else
- ADD_FAILURE() << "Non-fatal failure in some other thread. "
- << "(This failure is expected.)";
-}
-
-void GenerateFatalFailureInAnotherThread(bool is_fatal) {
- ThreadWithParam<bool> thread(&FailingThread, is_fatal, nullptr);
- thread.Join();
-}
-
-TEST(NoFatalFailureTest, ExpectNoFatalFailureIgnoresFailuresInOtherThreads) {
- EXPECT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
- // We should only have one failure (the one from
- // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
- // should succeed.
- CheckTestFailureCount(1);
-}
-
-void AssertNoFatalFailureIgnoresFailuresInOtherThreads() {
- ASSERT_NO_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true));
-}
-TEST(NoFatalFailureTest, AssertNoFatalFailureIgnoresFailuresInOtherThreads) {
- // Using a subroutine, to make sure, that the test continues.
- AssertNoFatalFailureIgnoresFailuresInOtherThreads();
- // We should only have one failure (the one from
- // GenerateFatalFailureInAnotherThread()), since the EXPECT_NO_FATAL_FAILURE
- // should succeed.
- CheckTestFailureCount(1);
-}
-
-TEST(FatalFailureTest, ExpectFatalFailureIgnoresFailuresInOtherThreads) {
- // This statement should fail, since the current thread doesn't generate a
- // fatal failure, only another one does.
- EXPECT_FATAL_FAILURE(GenerateFatalFailureInAnotherThread(true), "expected");
- CheckTestFailureCount(2);
-}
-
-TEST(FatalFailureOnAllThreadsTest, ExpectFatalFailureOnAllThreads) {
- // This statement should succeed, because failures in all threads are
- // considered.
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(
- GenerateFatalFailureInAnotherThread(true), "expected");
- CheckTestFailureCount(0);
- // We need to add a failure, because main() checks that there are failures.
- // But when only this test is run, we shouldn't have any failures.
- ADD_FAILURE() << "This is an expected non-fatal failure.";
-}
-
-TEST(NonFatalFailureTest, ExpectNonFatalFailureIgnoresFailuresInOtherThreads) {
- // This statement should fail, since the current thread doesn't generate a
- // fatal failure, only another one does.
- EXPECT_NONFATAL_FAILURE(GenerateFatalFailureInAnotherThread(false),
- "expected");
- CheckTestFailureCount(2);
-}
-
-TEST(NonFatalFailureOnAllThreadsTest, ExpectNonFatalFailureOnAllThreads) {
- // This statement should succeed, because failures in all threads are
- // considered.
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
- GenerateFatalFailureInAnotherThread(false), "expected");
- CheckTestFailureCount(0);
- // We need to add a failure, because main() checks that there are failures,
- // But when only this test is run, we shouldn't have any failures.
- ADD_FAILURE() << "This is an expected non-fatal failure.";
-}
-
-} // namespace
-} // namespace testing
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
-
- const int result = RUN_ALL_TESTS(); // Expected to fail.
- GTEST_CHECK_(result == 1) << "RUN_ALL_TESTS() did not fail as expected";
-
- printf("\nPASS\n");
- return 0;
-}
-
-#else
-TEST(StressTest,
- DISABLED_ThreadSafetyTestsAreSkippedWhenGoogleTestIsNotThreadSafe) {
-}
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-#endif // GTEST_IS_THREADSAFE
+++ /dev/null
-// Copyright 2013, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Each TEST() expands to some static registration logic. GCC puts all
-// such static initialization logic for a translation unit in a common,
-// internal function. Since Google's build system restricts how much
-// stack space a function can use, there's a limit on how many TEST()s
-// one can put in a single C++ test file. This test ensures that a large
-// number of TEST()s can be defined in the same translation unit.
-
-#include "gtest/gtest.h"
-
-// This macro defines 10 dummy tests.
-#define TEN_TESTS_(test_case_name) \
- TEST(test_case_name, T0) {} \
- TEST(test_case_name, T1) {} \
- TEST(test_case_name, T2) {} \
- TEST(test_case_name, T3) {} \
- TEST(test_case_name, T4) {} \
- TEST(test_case_name, T5) {} \
- TEST(test_case_name, T6) {} \
- TEST(test_case_name, T7) {} \
- TEST(test_case_name, T8) {} \
- TEST(test_case_name, T9) {}
-
-// This macro defines 100 dummy tests.
-#define HUNDRED_TESTS_(test_case_name_prefix) \
- TEN_TESTS_(test_case_name_prefix ## 0) \
- TEN_TESTS_(test_case_name_prefix ## 1) \
- TEN_TESTS_(test_case_name_prefix ## 2) \
- TEN_TESTS_(test_case_name_prefix ## 3) \
- TEN_TESTS_(test_case_name_prefix ## 4) \
- TEN_TESTS_(test_case_name_prefix ## 5) \
- TEN_TESTS_(test_case_name_prefix ## 6) \
- TEN_TESTS_(test_case_name_prefix ## 7) \
- TEN_TESTS_(test_case_name_prefix ## 8) \
- TEN_TESTS_(test_case_name_prefix ## 9)
-
-// This macro defines 1000 dummy tests.
-#define THOUSAND_TESTS_(test_case_name_prefix) \
- HUNDRED_TESTS_(test_case_name_prefix ## 0) \
- HUNDRED_TESTS_(test_case_name_prefix ## 1) \
- HUNDRED_TESTS_(test_case_name_prefix ## 2) \
- HUNDRED_TESTS_(test_case_name_prefix ## 3) \
- HUNDRED_TESTS_(test_case_name_prefix ## 4) \
- HUNDRED_TESTS_(test_case_name_prefix ## 5) \
- HUNDRED_TESTS_(test_case_name_prefix ## 6) \
- HUNDRED_TESTS_(test_case_name_prefix ## 7) \
- HUNDRED_TESTS_(test_case_name_prefix ## 8) \
- HUNDRED_TESTS_(test_case_name_prefix ## 9)
-
-// Ensures that we can define 1000 TEST()s in the same translation
-// unit.
-THOUSAND_TESTS_(T)
-
-int main(int argc, char **argv) {
- testing::InitGoogleTest(&argc, argv);
-
- // We don't actually need to run the dummy tests - the purpose is to
- // ensure that they compile.
- return 0;
-}
+++ /dev/null
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test utilities for Google C++ Testing and Mocking Framework."""
-# Suppresses the 'Import not at the top of the file' lint complaint.
-# pylint: disable-msg=C6204
-
-import os
-import sys
-
-IS_WINDOWS = os.name == 'nt'
-IS_CYGWIN = os.name == 'posix' and 'CYGWIN' in os.uname()[0]
-IS_OS2 = os.name == 'os2'
-
-import atexit
-import shutil
-import tempfile
-import unittest as _test_module
-
-try:
- import subprocess
- _SUBPROCESS_MODULE_AVAILABLE = True
-except:
- import popen2
- _SUBPROCESS_MODULE_AVAILABLE = False
-# pylint: enable-msg=C6204
-
-GTEST_OUTPUT_VAR_NAME = 'GTEST_OUTPUT'
-
-# The environment variable for specifying the path to the premature-exit file.
-PREMATURE_EXIT_FILE_ENV_VAR = 'TEST_PREMATURE_EXIT_FILE'
-
-environ = os.environ.copy()
-
-
-def SetEnvVar(env_var, value):
- """Sets/unsets an environment variable to a given value."""
-
- if value is not None:
- environ[env_var] = value
- elif env_var in environ:
- del environ[env_var]
-
-
-# Here we expose a class from a particular module, depending on the
-# environment. The comment suppresses the 'Invalid variable name' lint
-# complaint.
-TestCase = _test_module.TestCase # pylint: disable=C6409
-
-# Initially maps a flag to its default value. After
-# _ParseAndStripGTestFlags() is called, maps a flag to its actual value.
-_flag_map = {'source_dir': os.path.dirname(sys.argv[0]),
- 'build_dir': os.path.dirname(sys.argv[0])}
-_gtest_flags_are_parsed = False
-
-
-def _ParseAndStripGTestFlags(argv):
- """Parses and strips Google Test flags from argv. This is idempotent."""
-
- # Suppresses the lint complaint about a global variable since we need it
- # here to maintain module-wide state.
- global _gtest_flags_are_parsed # pylint: disable=W0603
- if _gtest_flags_are_parsed:
- return
-
- _gtest_flags_are_parsed = True
- for flag in _flag_map:
- # The environment variable overrides the default value.
- if flag.upper() in os.environ:
- _flag_map[flag] = os.environ[flag.upper()]
-
- # The command line flag overrides the environment variable.
- i = 1 # Skips the program name.
- while i < len(argv):
- prefix = '--' + flag + '='
- if argv[i].startswith(prefix):
- _flag_map[flag] = argv[i][len(prefix):]
- del argv[i]
- break
- else:
- # We don't increment i in case we just found a --gtest_* flag
- # and removed it from argv.
- i += 1
-
-
-def GetFlag(flag):
- """Returns the value of the given flag."""
-
- # In case GetFlag() is called before Main(), we always call
- # _ParseAndStripGTestFlags() here to make sure the --gtest_* flags
- # are parsed.
- _ParseAndStripGTestFlags(sys.argv)
-
- return _flag_map[flag]
-
-
-def GetSourceDir():
- """Returns the absolute path of the directory where the .py files are."""
-
- return os.path.abspath(GetFlag('source_dir'))
-
-
-def GetBuildDir():
- """Returns the absolute path of the directory where the test binaries are."""
-
- return os.path.abspath(GetFlag('build_dir'))
-
-
-_temp_dir = None
-
-def _RemoveTempDir():
- if _temp_dir:
- shutil.rmtree(_temp_dir, ignore_errors=True)
-
-atexit.register(_RemoveTempDir)
-
-
-def GetTempDir():
- global _temp_dir
- if not _temp_dir:
- _temp_dir = tempfile.mkdtemp()
- return _temp_dir
-
-
-def GetTestExecutablePath(executable_name, build_dir=None):
- """Returns the absolute path of the test binary given its name.
-
- The function will print a message and abort the program if the resulting file
- doesn't exist.
-
- Args:
- executable_name: name of the test binary that the test script runs.
- build_dir: directory where to look for executables, by default
- the result of GetBuildDir().
-
- Returns:
- The absolute path of the test binary.
- """
-
- path = os.path.abspath(os.path.join(build_dir or GetBuildDir(),
- executable_name))
- if (IS_WINDOWS or IS_CYGWIN or IS_OS2) and not path.endswith('.exe'):
- path += '.exe'
-
- if not os.path.exists(path):
- message = (
- 'Unable to find the test binary "%s". Please make sure to provide\n'
- 'a path to the binary via the --build_dir flag or the BUILD_DIR\n'
- 'environment variable.' % path)
- print >> sys.stderr, message
- sys.exit(1)
-
- return path
-
-
-def GetExitStatus(exit_code):
- """Returns the argument to exit(), or -1 if exit() wasn't called.
-
- Args:
- exit_code: the result value of os.system(command).
- """
-
- if os.name == 'nt':
- # On Windows, os.WEXITSTATUS() doesn't work and os.system() returns
- # the argument to exit() directly.
- return exit_code
- else:
- # On Unix, os.WEXITSTATUS() must be used to extract the exit status
- # from the result of os.system().
- if os.WIFEXITED(exit_code):
- return os.WEXITSTATUS(exit_code)
- else:
- return -1
-
-
-class Subprocess:
- def __init__(self, command, working_dir=None, capture_stderr=True, env=None):
- """Changes into a specified directory, if provided, and executes a command.
-
- Restores the old directory afterwards.
-
- Args:
- command: The command to run, in the form of sys.argv.
- working_dir: The directory to change into.
- capture_stderr: Determines whether to capture stderr in the output member
- or to discard it.
- env: Dictionary with environment to pass to the subprocess.
-
- Returns:
- An object that represents outcome of the executed process. It has the
- following attributes:
- terminated_by_signal True if and only if the child process has been
- terminated by a signal.
- signal Sygnal that terminated the child process.
- exited True if and only if the child process exited
- normally.
- exit_code The code with which the child process exited.
- output Child process's stdout and stderr output
- combined in a string.
- """
-
- # The subprocess module is the preferrable way of running programs
- # since it is available and behaves consistently on all platforms,
- # including Windows. But it is only available starting in python 2.4.
- # In earlier python versions, we revert to the popen2 module, which is
- # available in python 2.0 and later but doesn't provide required
- # functionality (Popen4) under Windows. This allows us to support Mac
- # OS X 10.4 Tiger, which has python 2.3 installed.
- if _SUBPROCESS_MODULE_AVAILABLE:
- if capture_stderr:
- stderr = subprocess.STDOUT
- else:
- stderr = subprocess.PIPE
-
- p = subprocess.Popen(command,
- stdout=subprocess.PIPE, stderr=stderr,
- cwd=working_dir, universal_newlines=True, env=env)
- # communicate returns a tuple with the file object for the child's
- # output.
- self.output = p.communicate()[0]
- self._return_code = p.returncode
- else:
- old_dir = os.getcwd()
-
- def _ReplaceEnvDict(dest, src):
- # Changes made by os.environ.clear are not inheritable by child
- # processes until Python 2.6. To produce inheritable changes we have
- # to delete environment items with the del statement.
- for key in dest.keys():
- del dest[key]
- dest.update(src)
-
- # When 'env' is not None, backup the environment variables and replace
- # them with the passed 'env'. When 'env' is None, we simply use the
- # current 'os.environ' for compatibility with the subprocess.Popen
- # semantics used above.
- if env is not None:
- old_environ = os.environ.copy()
- _ReplaceEnvDict(os.environ, env)
-
- try:
- if working_dir is not None:
- os.chdir(working_dir)
- if capture_stderr:
- p = popen2.Popen4(command)
- else:
- p = popen2.Popen3(command)
- p.tochild.close()
- self.output = p.fromchild.read()
- ret_code = p.wait()
- finally:
- os.chdir(old_dir)
-
- # Restore the old environment variables
- # if they were replaced.
- if env is not None:
- _ReplaceEnvDict(os.environ, old_environ)
-
- # Converts ret_code to match the semantics of
- # subprocess.Popen.returncode.
- if os.WIFSIGNALED(ret_code):
- self._return_code = -os.WTERMSIG(ret_code)
- else: # os.WIFEXITED(ret_code) should return True here.
- self._return_code = os.WEXITSTATUS(ret_code)
-
- if self._return_code < 0:
- self.terminated_by_signal = True
- self.exited = False
- self.signal = -self._return_code
- else:
- self.terminated_by_signal = False
- self.exited = True
- self.exit_code = self._return_code
-
-
-def Main():
- """Runs the unit test."""
-
- # We must call _ParseAndStripGTestFlags() before calling
- # unittest.main(). Otherwise the latter will be confused by the
- # --gtest_* flags.
- _ParseAndStripGTestFlags(sys.argv)
- # The tested binaries should not be writing XML output files unless the
- # script explicitly instructs them to.
- if GTEST_OUTPUT_VAR_NAME in os.environ:
- del os.environ[GTEST_OUTPUT_VAR_NAME]
-
- _test_module.main()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2018 Google LLC. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""Verifies that Google Test uses filter provided via testbridge."""
-
-import os
-
-import gtest_test_utils
-
-binary_name = 'gtest_testbridge_test_'
-COMMAND = gtest_test_utils.GetTestExecutablePath(binary_name)
-TESTBRIDGE_NAME = 'TESTBRIDGE_TEST_ONLY'
-
-
-def Assert(condition):
- if not condition:
- raise AssertionError
-
-
-class GTestTestFilterTest(gtest_test_utils.TestCase):
-
- def testTestExecutionIsFiltered(self):
- """Tests that the test filter is picked up from the testbridge env var."""
- subprocess_env = os.environ.copy()
-
- subprocess_env[TESTBRIDGE_NAME] = '*.TestThatSucceeds'
- p = gtest_test_utils.Subprocess(COMMAND, env=subprocess_env)
-
- self.assertEquals(0, p.exit_code)
-
- Assert('filter = *.TestThatSucceeds' in p.output)
- Assert('[ OK ] TestFilterTest.TestThatSucceeds' in p.output)
- Assert('[ PASSED ] 1 test.' in p.output)
-
-
-if __name__ == '__main__':
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2018, Google LLC.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// This program is meant to be run by gtest_test_filter_test.py. Do not run
-// it directly.
-
-#include "gtest/gtest.h"
-
-// These tests are used to detect if filtering is working. Only
-// 'TestThatSucceeds' should ever run.
-
-TEST(TestFilterTest, TestThatSucceeds) {}
-
-TEST(TestFilterTest, TestThatFails) {
- ASSERT_TRUE(false) << "This test should never be run.";
-}
+++ /dev/null
-// Copyright 2009, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-// Tests Google Test's throw-on-failure mode with exceptions enabled.
-
-#include "gtest/gtest.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdexcept>
-
-// Prints the given failure message and exits the program with
-// non-zero. We use this instead of a Google Test assertion to
-// indicate a failure, as the latter is been tested and cannot be
-// relied on.
-void Fail(const char* msg) {
- printf("FAILURE: %s\n", msg);
- fflush(stdout);
- exit(1);
-}
-
-// Tests that an assertion failure throws a subclass of
-// std::runtime_error.
-void TestFailureThrowsRuntimeError() {
- testing::GTEST_FLAG(throw_on_failure) = true;
-
- // A successful assertion shouldn't throw.
- try {
- EXPECT_EQ(3, 3);
- } catch(...) {
- Fail("A successful assertion wrongfully threw.");
- }
-
- // A failed assertion should throw a subclass of std::runtime_error.
- try {
- EXPECT_EQ(2, 3) << "Expected failure";
- } catch(const std::runtime_error& e) {
- if (strstr(e.what(), "Expected failure") != nullptr) return;
-
- printf("%s",
- "A failed assertion did throw an exception of the right type, "
- "but the message is incorrect. Instead of containing \"Expected "
- "failure\", it is:\n");
- Fail(e.what());
- } catch(...) {
- Fail("A failed assertion threw the wrong type of exception.");
- }
- Fail("A failed assertion should've thrown but didn't.");
-}
-
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
-
- // We want to ensure that people can use Google Test assertions in
- // other testing frameworks, as long as they initialize Google Test
- // properly and set the thrown-on-failure mode. Therefore, we don't
- // use Google Test's constructs for defining and running tests
- // (e.g. TEST and RUN_ALL_TESTS) here.
-
- TestFailureThrowsRuntimeError();
- return 0;
-}
+++ /dev/null
-// Copyright 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// Tests for Google Test itself. This verifies that the basic constructs of
-// Google Test work.
-
-#include "gtest/gtest.h"
-
-// Verifies that the command line flag variables can be accessed in
-// code once "gtest.h" has been #included.
-// Do not move it after other gtest #includes.
-TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
- bool dummy = testing::GTEST_FLAG(also_run_disabled_tests)
- || testing::GTEST_FLAG(break_on_failure)
- || testing::GTEST_FLAG(catch_exceptions)
- || testing::GTEST_FLAG(color) != "unknown"
- || testing::GTEST_FLAG(filter) != "unknown"
- || testing::GTEST_FLAG(list_tests)
- || testing::GTEST_FLAG(output) != "unknown"
- || testing::GTEST_FLAG(print_time)
- || testing::GTEST_FLAG(random_seed)
- || testing::GTEST_FLAG(repeat) > 0
- || testing::GTEST_FLAG(show_internal_stack_frames)
- || testing::GTEST_FLAG(shuffle)
- || testing::GTEST_FLAG(stack_trace_depth) > 0
- || testing::GTEST_FLAG(stream_result_to) != "unknown"
- || testing::GTEST_FLAG(throw_on_failure);
- EXPECT_TRUE(dummy || !dummy); // Suppresses warning that dummy is unused.
-}
-
-#include <limits.h> // For INT_MAX.
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <map>
-#include <ostream>
-#include <type_traits>
-#include <unordered_set>
-#include <vector>
-
-#include "gtest/gtest-spi.h"
-#include "src/gtest-internal-inl.h"
-
-namespace testing {
-namespace internal {
-
-#if GTEST_CAN_STREAM_RESULTS_
-
-class StreamingListenerTest : public Test {
- public:
- class FakeSocketWriter : public StreamingListener::AbstractSocketWriter {
- public:
- // Sends a string to the socket.
- void Send(const std::string& message) override { output_ += message; }
-
- std::string output_;
- };
-
- StreamingListenerTest()
- : fake_sock_writer_(new FakeSocketWriter),
- streamer_(fake_sock_writer_),
- test_info_obj_("FooTest", "Bar", nullptr, nullptr,
- CodeLocation(__FILE__, __LINE__), nullptr, nullptr) {}
-
- protected:
- std::string* output() { return &(fake_sock_writer_->output_); }
-
- FakeSocketWriter* const fake_sock_writer_;
- StreamingListener streamer_;
- UnitTest unit_test_;
- TestInfo test_info_obj_; // The name test_info_ was taken by testing::Test.
-};
-
-TEST_F(StreamingListenerTest, OnTestProgramEnd) {
- *output() = "";
- streamer_.OnTestProgramEnd(unit_test_);
- EXPECT_EQ("event=TestProgramEnd&passed=1\n", *output());
-}
-
-TEST_F(StreamingListenerTest, OnTestIterationEnd) {
- *output() = "";
- streamer_.OnTestIterationEnd(unit_test_, 42);
- EXPECT_EQ("event=TestIterationEnd&passed=1&elapsed_time=0ms\n", *output());
-}
-
-TEST_F(StreamingListenerTest, OnTestCaseStart) {
- *output() = "";
- streamer_.OnTestCaseStart(TestCase("FooTest", "Bar", nullptr, nullptr));
- EXPECT_EQ("event=TestCaseStart&name=FooTest\n", *output());
-}
-
-TEST_F(StreamingListenerTest, OnTestCaseEnd) {
- *output() = "";
- streamer_.OnTestCaseEnd(TestCase("FooTest", "Bar", nullptr, nullptr));
- EXPECT_EQ("event=TestCaseEnd&passed=1&elapsed_time=0ms\n", *output());
-}
-
-TEST_F(StreamingListenerTest, OnTestStart) {
- *output() = "";
- streamer_.OnTestStart(test_info_obj_);
- EXPECT_EQ("event=TestStart&name=Bar\n", *output());
-}
-
-TEST_F(StreamingListenerTest, OnTestEnd) {
- *output() = "";
- streamer_.OnTestEnd(test_info_obj_);
- EXPECT_EQ("event=TestEnd&passed=1&elapsed_time=0ms\n", *output());
-}
-
-TEST_F(StreamingListenerTest, OnTestPartResult) {
- *output() = "";
- streamer_.OnTestPartResult(TestPartResult(
- TestPartResult::kFatalFailure, "foo.cc", 42, "failed=\n&%"));
-
- // Meta characters in the failure message should be properly escaped.
- EXPECT_EQ(
- "event=TestPartResult&file=foo.cc&line=42&message=failed%3D%0A%26%25\n",
- *output());
-}
-
-#endif // GTEST_CAN_STREAM_RESULTS_
-
-// Provides access to otherwise private parts of the TestEventListeners class
-// that are needed to test it.
-class TestEventListenersAccessor {
- public:
- static TestEventListener* GetRepeater(TestEventListeners* listeners) {
- return listeners->repeater();
- }
-
- static void SetDefaultResultPrinter(TestEventListeners* listeners,
- TestEventListener* listener) {
- listeners->SetDefaultResultPrinter(listener);
- }
- static void SetDefaultXmlGenerator(TestEventListeners* listeners,
- TestEventListener* listener) {
- listeners->SetDefaultXmlGenerator(listener);
- }
-
- static bool EventForwardingEnabled(const TestEventListeners& listeners) {
- return listeners.EventForwardingEnabled();
- }
-
- static void SuppressEventForwarding(TestEventListeners* listeners) {
- listeners->SuppressEventForwarding();
- }
-};
-
-class UnitTestRecordPropertyTestHelper : public Test {
- protected:
- UnitTestRecordPropertyTestHelper() {}
-
- // Forwards to UnitTest::RecordProperty() to bypass access controls.
- void UnitTestRecordProperty(const char* key, const std::string& value) {
- unit_test_.RecordProperty(key, value);
- }
-
- UnitTest unit_test_;
-};
-
-} // namespace internal
-} // namespace testing
-
-using testing::AssertionFailure;
-using testing::AssertionResult;
-using testing::AssertionSuccess;
-using testing::DoubleLE;
-using testing::EmptyTestEventListener;
-using testing::Environment;
-using testing::FloatLE;
-using testing::GTEST_FLAG(also_run_disabled_tests);
-using testing::GTEST_FLAG(break_on_failure);
-using testing::GTEST_FLAG(catch_exceptions);
-using testing::GTEST_FLAG(color);
-using testing::GTEST_FLAG(death_test_use_fork);
-using testing::GTEST_FLAG(filter);
-using testing::GTEST_FLAG(list_tests);
-using testing::GTEST_FLAG(output);
-using testing::GTEST_FLAG(print_time);
-using testing::GTEST_FLAG(random_seed);
-using testing::GTEST_FLAG(repeat);
-using testing::GTEST_FLAG(show_internal_stack_frames);
-using testing::GTEST_FLAG(shuffle);
-using testing::GTEST_FLAG(stack_trace_depth);
-using testing::GTEST_FLAG(stream_result_to);
-using testing::GTEST_FLAG(throw_on_failure);
-using testing::IsNotSubstring;
-using testing::IsSubstring;
-using testing::Message;
-using testing::ScopedFakeTestPartResultReporter;
-using testing::StaticAssertTypeEq;
-using testing::Test;
-using testing::TestCase;
-using testing::TestEventListeners;
-using testing::TestInfo;
-using testing::TestPartResult;
-using testing::TestPartResultArray;
-using testing::TestProperty;
-using testing::TestResult;
-using testing::TimeInMillis;
-using testing::UnitTest;
-using testing::internal::AlwaysFalse;
-using testing::internal::AlwaysTrue;
-using testing::internal::AppendUserMessage;
-using testing::internal::ArrayAwareFind;
-using testing::internal::ArrayEq;
-using testing::internal::CodePointToUtf8;
-using testing::internal::CopyArray;
-using testing::internal::CountIf;
-using testing::internal::EqFailure;
-using testing::internal::FloatingPoint;
-using testing::internal::ForEach;
-using testing::internal::FormatEpochTimeInMillisAsIso8601;
-using testing::internal::FormatTimeInMillisAsSeconds;
-using testing::internal::GTestFlagSaver;
-using testing::internal::GetCurrentOsStackTraceExceptTop;
-using testing::internal::GetElementOr;
-using testing::internal::GetNextRandomSeed;
-using testing::internal::GetRandomSeedFromFlag;
-using testing::internal::GetTestTypeId;
-using testing::internal::GetTimeInMillis;
-using testing::internal::GetTypeId;
-using testing::internal::GetUnitTestImpl;
-using testing::internal::Int32;
-using testing::internal::Int32FromEnvOrDie;
-using testing::internal::IsAProtocolMessage;
-using testing::internal::IsContainer;
-using testing::internal::IsContainerTest;
-using testing::internal::IsNotContainer;
-using testing::internal::NativeArray;
-using testing::internal::OsStackTraceGetter;
-using testing::internal::OsStackTraceGetterInterface;
-using testing::internal::ParseInt32Flag;
-using testing::internal::RelationToSourceCopy;
-using testing::internal::RelationToSourceReference;
-using testing::internal::ShouldRunTestOnShard;
-using testing::internal::ShouldShard;
-using testing::internal::ShouldUseColor;
-using testing::internal::Shuffle;
-using testing::internal::ShuffleRange;
-using testing::internal::SkipPrefix;
-using testing::internal::StreamableToString;
-using testing::internal::String;
-using testing::internal::TestEventListenersAccessor;
-using testing::internal::TestResultAccessor;
-using testing::internal::UInt32;
-using testing::internal::UnitTestImpl;
-using testing::internal::WideStringToUtf8;
-using testing::internal::edit_distance::CalculateOptimalEdits;
-using testing::internal::edit_distance::CreateUnifiedDiff;
-using testing::internal::edit_distance::EditType;
-using testing::internal::kMaxRandomSeed;
-using testing::internal::kTestTypeIdInGoogleTest;
-using testing::kMaxStackTraceDepth;
-
-#if GTEST_HAS_STREAM_REDIRECTION
-using testing::internal::CaptureStdout;
-using testing::internal::GetCapturedStdout;
-#endif
-
-#if GTEST_IS_THREADSAFE
-using testing::internal::ThreadWithParam;
-#endif
-
-class TestingVector : public std::vector<int> {
-};
-
-::std::ostream& operator<<(::std::ostream& os,
- const TestingVector& vector) {
- os << "{ ";
- for (size_t i = 0; i < vector.size(); i++) {
- os << vector[i] << " ";
- }
- os << "}";
- return os;
-}
-
-// This line tests that we can define tests in an unnamed namespace.
-namespace {
-
-TEST(GetRandomSeedFromFlagTest, HandlesZero) {
- const int seed = GetRandomSeedFromFlag(0);
- EXPECT_LE(1, seed);
- EXPECT_LE(seed, static_cast<int>(kMaxRandomSeed));
-}
-
-TEST(GetRandomSeedFromFlagTest, PreservesValidSeed) {
- EXPECT_EQ(1, GetRandomSeedFromFlag(1));
- EXPECT_EQ(2, GetRandomSeedFromFlag(2));
- EXPECT_EQ(kMaxRandomSeed - 1, GetRandomSeedFromFlag(kMaxRandomSeed - 1));
- EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
- GetRandomSeedFromFlag(kMaxRandomSeed));
-}
-
-TEST(GetRandomSeedFromFlagTest, NormalizesInvalidSeed) {
- const int seed1 = GetRandomSeedFromFlag(-1);
- EXPECT_LE(1, seed1);
- EXPECT_LE(seed1, static_cast<int>(kMaxRandomSeed));
-
- const int seed2 = GetRandomSeedFromFlag(kMaxRandomSeed + 1);
- EXPECT_LE(1, seed2);
- EXPECT_LE(seed2, static_cast<int>(kMaxRandomSeed));
-}
-
-TEST(GetNextRandomSeedTest, WorksForValidInput) {
- EXPECT_EQ(2, GetNextRandomSeed(1));
- EXPECT_EQ(3, GetNextRandomSeed(2));
- EXPECT_EQ(static_cast<int>(kMaxRandomSeed),
- GetNextRandomSeed(kMaxRandomSeed - 1));
- EXPECT_EQ(1, GetNextRandomSeed(kMaxRandomSeed));
-
- // We deliberately don't test GetNextRandomSeed() with invalid
- // inputs, as that requires death tests, which are expensive. This
- // is fine as GetNextRandomSeed() is internal and has a
- // straightforward definition.
-}
-
-static void ClearCurrentTestPartResults() {
- TestResultAccessor::ClearTestPartResults(
- GetUnitTestImpl()->current_test_result());
-}
-
-// Tests GetTypeId.
-
-TEST(GetTypeIdTest, ReturnsSameValueForSameType) {
- EXPECT_EQ(GetTypeId<int>(), GetTypeId<int>());
- EXPECT_EQ(GetTypeId<Test>(), GetTypeId<Test>());
-}
-
-class SubClassOfTest : public Test {};
-class AnotherSubClassOfTest : public Test {};
-
-TEST(GetTypeIdTest, ReturnsDifferentValuesForDifferentTypes) {
- EXPECT_NE(GetTypeId<int>(), GetTypeId<const int>());
- EXPECT_NE(GetTypeId<int>(), GetTypeId<char>());
- EXPECT_NE(GetTypeId<int>(), GetTestTypeId());
- EXPECT_NE(GetTypeId<SubClassOfTest>(), GetTestTypeId());
- EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTestTypeId());
- EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTypeId<SubClassOfTest>());
-}
-
-// Verifies that GetTestTypeId() returns the same value, no matter it
-// is called from inside Google Test or outside of it.
-TEST(GetTestTypeIdTest, ReturnsTheSameValueInsideOrOutsideOfGoogleTest) {
- EXPECT_EQ(kTestTypeIdInGoogleTest, GetTestTypeId());
-}
-
-// Tests CanonicalizeForStdLibVersioning.
-
-using ::testing::internal::CanonicalizeForStdLibVersioning;
-
-TEST(CanonicalizeForStdLibVersioning, LeavesUnversionedNamesUnchanged) {
- EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::bind"));
- EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::_"));
- EXPECT_EQ("std::__foo", CanonicalizeForStdLibVersioning("std::__foo"));
- EXPECT_EQ("gtl::__1::x", CanonicalizeForStdLibVersioning("gtl::__1::x"));
- EXPECT_EQ("__1::x", CanonicalizeForStdLibVersioning("__1::x"));
- EXPECT_EQ("::__1::x", CanonicalizeForStdLibVersioning("::__1::x"));
-}
-
-TEST(CanonicalizeForStdLibVersioning, ElidesDoubleUnderNames) {
- EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::__1::bind"));
- EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::__1::_"));
-
- EXPECT_EQ("std::bind", CanonicalizeForStdLibVersioning("std::__g::bind"));
- EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::__g::_"));
-
- EXPECT_EQ("std::bind",
- CanonicalizeForStdLibVersioning("std::__google::bind"));
- EXPECT_EQ("std::_", CanonicalizeForStdLibVersioning("std::__google::_"));
-}
-
-// Tests FormatTimeInMillisAsSeconds().
-
-TEST(FormatTimeInMillisAsSecondsTest, FormatsZero) {
- EXPECT_EQ("0", FormatTimeInMillisAsSeconds(0));
-}
-
-TEST(FormatTimeInMillisAsSecondsTest, FormatsPositiveNumber) {
- EXPECT_EQ("0.003", FormatTimeInMillisAsSeconds(3));
- EXPECT_EQ("0.01", FormatTimeInMillisAsSeconds(10));
- EXPECT_EQ("0.2", FormatTimeInMillisAsSeconds(200));
- EXPECT_EQ("1.2", FormatTimeInMillisAsSeconds(1200));
- EXPECT_EQ("3", FormatTimeInMillisAsSeconds(3000));
-}
-
-TEST(FormatTimeInMillisAsSecondsTest, FormatsNegativeNumber) {
- EXPECT_EQ("-0.003", FormatTimeInMillisAsSeconds(-3));
- EXPECT_EQ("-0.01", FormatTimeInMillisAsSeconds(-10));
- EXPECT_EQ("-0.2", FormatTimeInMillisAsSeconds(-200));
- EXPECT_EQ("-1.2", FormatTimeInMillisAsSeconds(-1200));
- EXPECT_EQ("-3", FormatTimeInMillisAsSeconds(-3000));
-}
-
-// Tests FormatEpochTimeInMillisAsIso8601(). The correctness of conversion
-// for particular dates below was verified in Python using
-// datetime.datetime.fromutctimestamp(<timetamp>/1000).
-
-// FormatEpochTimeInMillisAsIso8601 depends on the current timezone, so we
-// have to set up a particular timezone to obtain predictable results.
-class FormatEpochTimeInMillisAsIso8601Test : public Test {
- public:
- // On Cygwin, GCC doesn't allow unqualified integer literals to exceed
- // 32 bits, even when 64-bit integer types are available. We have to
- // force the constants to have a 64-bit type here.
- static const TimeInMillis kMillisPerSec = 1000;
-
- private:
- void SetUp() override {
- saved_tz_ = nullptr;
-
- GTEST_DISABLE_MSC_DEPRECATED_PUSH_(/* getenv, strdup: deprecated */)
- if (getenv("TZ"))
- saved_tz_ = strdup(getenv("TZ"));
- GTEST_DISABLE_MSC_DEPRECATED_POP_()
-
- // Set up the time zone for FormatEpochTimeInMillisAsIso8601 to use. We
- // cannot use the local time zone because the function's output depends
- // on the time zone.
- SetTimeZone("UTC+00");
- }
-
- void TearDown() override {
- SetTimeZone(saved_tz_);
- free(const_cast<char*>(saved_tz_));
- saved_tz_ = nullptr;
- }
-
- static void SetTimeZone(const char* time_zone) {
- // tzset() distinguishes between the TZ variable being present and empty
- // and not being present, so we have to consider the case of time_zone
- // being NULL.
-#if _MSC_VER || GTEST_OS_WINDOWS_MINGW
- // ...Unless it's MSVC, whose standard library's _putenv doesn't
- // distinguish between an empty and a missing variable.
- const std::string env_var =
- std::string("TZ=") + (time_zone ? time_zone : "");
- _putenv(env_var.c_str());
- GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996 /* deprecated function */)
- tzset();
- GTEST_DISABLE_MSC_WARNINGS_POP_()
-#else
- if (time_zone) {
- setenv(("TZ"), time_zone, 1);
- } else {
- unsetenv("TZ");
- }
- tzset();
-#endif
- }
-
- const char* saved_tz_;
-};
-
-const TimeInMillis FormatEpochTimeInMillisAsIso8601Test::kMillisPerSec;
-
-TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsTwoDigitSegments) {
- EXPECT_EQ("2011-10-31T18:52:42",
- FormatEpochTimeInMillisAsIso8601(1320087162 * kMillisPerSec));
-}
-
-TEST_F(FormatEpochTimeInMillisAsIso8601Test, MillisecondsDoNotAffectResult) {
- EXPECT_EQ(
- "2011-10-31T18:52:42",
- FormatEpochTimeInMillisAsIso8601(1320087162 * kMillisPerSec + 234));
-}
-
-TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsLeadingZeroes) {
- EXPECT_EQ("2011-09-03T05:07:02",
- FormatEpochTimeInMillisAsIso8601(1315026422 * kMillisPerSec));
-}
-
-TEST_F(FormatEpochTimeInMillisAsIso8601Test, Prints24HourTime) {
- EXPECT_EQ("2011-09-28T17:08:22",
- FormatEpochTimeInMillisAsIso8601(1317229702 * kMillisPerSec));
-}
-
-TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsEpochStart) {
- EXPECT_EQ("1970-01-01T00:00:00", FormatEpochTimeInMillisAsIso8601(0));
-}
-
-# ifdef __BORLANDC__
-// Silences warnings: "Condition is always true", "Unreachable code"
-# pragma option push -w-ccc -w-rch
-# endif
-
-// Tests that the LHS of EXPECT_EQ or ASSERT_EQ can be used as a null literal
-// when the RHS is a pointer type.
-TEST(NullLiteralTest, LHSAllowsNullLiterals) {
- EXPECT_EQ(0, static_cast<void*>(nullptr)); // NOLINT
- ASSERT_EQ(0, static_cast<void*>(nullptr)); // NOLINT
- EXPECT_EQ(NULL, static_cast<void*>(nullptr)); // NOLINT
- ASSERT_EQ(NULL, static_cast<void*>(nullptr)); // NOLINT
- EXPECT_EQ(nullptr, static_cast<void*>(nullptr));
- ASSERT_EQ(nullptr, static_cast<void*>(nullptr));
-
- const int* const p = nullptr;
- EXPECT_EQ(0, p); // NOLINT
- ASSERT_EQ(0, p); // NOLINT
- EXPECT_EQ(NULL, p); // NOLINT
- ASSERT_EQ(NULL, p); // NOLINT
- EXPECT_EQ(nullptr, p);
- ASSERT_EQ(nullptr, p);
-}
-
-struct ConvertToAll {
- template <typename T>
- operator T() const { // NOLINT
- return T();
- }
-};
-
-struct ConvertToPointer {
- template <class T>
- operator T*() const { // NOLINT
- return nullptr;
- }
-};
-
-struct ConvertToAllButNoPointers {
- template <typename T,
- typename std::enable_if<!std::is_pointer<T>::value, int>::type = 0>
- operator T() const { // NOLINT
- return T();
- }
-};
-
-struct MyType {};
-inline bool operator==(MyType const&, MyType const&) { return true; }
-
-TEST(NullLiteralTest, ImplicitConversion) {
- EXPECT_EQ(ConvertToPointer{}, static_cast<void*>(nullptr));
-#if !defined(__GNUC__) || defined(__clang__)
- // Disabled due to GCC bug gcc.gnu.org/PR89580
- EXPECT_EQ(ConvertToAll{}, static_cast<void*>(nullptr));
-#endif
- EXPECT_EQ(ConvertToAll{}, MyType{});
- EXPECT_EQ(ConvertToAllButNoPointers{}, MyType{});
-}
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#if __has_warning("-Wzero-as-null-pointer-constant")
-#pragma clang diagnostic error "-Wzero-as-null-pointer-constant"
-#endif
-#endif
-
-TEST(NullLiteralTest, NoConversionNoWarning) {
- // Test that gtests detection and handling of null pointer constants
- // doesn't trigger a warning when '0' isn't actually used as null.
- EXPECT_EQ(0, 0);
- ASSERT_EQ(0, 0);
-}
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
-
-# ifdef __BORLANDC__
-// Restores warnings after previous "#pragma option push" suppressed them.
-# pragma option pop
-# endif
-
-//
-// Tests CodePointToUtf8().
-
-// Tests that the NUL character L'\0' is encoded correctly.
-TEST(CodePointToUtf8Test, CanEncodeNul) {
- EXPECT_EQ("", CodePointToUtf8(L'\0'));
-}
-
-// Tests that ASCII characters are encoded correctly.
-TEST(CodePointToUtf8Test, CanEncodeAscii) {
- EXPECT_EQ("a", CodePointToUtf8(L'a'));
- EXPECT_EQ("Z", CodePointToUtf8(L'Z'));
- EXPECT_EQ("&", CodePointToUtf8(L'&'));
- EXPECT_EQ("\x7F", CodePointToUtf8(L'\x7F'));
-}
-
-// Tests that Unicode code-points that have 8 to 11 bits are encoded
-// as 110xxxxx 10xxxxxx.
-TEST(CodePointToUtf8Test, CanEncode8To11Bits) {
- // 000 1101 0011 => 110-00011 10-010011
- EXPECT_EQ("\xC3\x93", CodePointToUtf8(L'\xD3'));
-
- // 101 0111 0110 => 110-10101 10-110110
- // Some compilers (e.g., GCC on MinGW) cannot handle non-ASCII codepoints
- // in wide strings and wide chars. In order to accommodate them, we have to
- // introduce such character constants as integers.
- EXPECT_EQ("\xD5\xB6",
- CodePointToUtf8(static_cast<wchar_t>(0x576)));
-}
-
-// Tests that Unicode code-points that have 12 to 16 bits are encoded
-// as 1110xxxx 10xxxxxx 10xxxxxx.
-TEST(CodePointToUtf8Test, CanEncode12To16Bits) {
- // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
- EXPECT_EQ("\xE0\xA3\x93",
- CodePointToUtf8(static_cast<wchar_t>(0x8D3)));
-
- // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
- EXPECT_EQ("\xEC\x9D\x8D",
- CodePointToUtf8(static_cast<wchar_t>(0xC74D)));
-}
-
-#if !GTEST_WIDE_STRING_USES_UTF16_
-// Tests in this group require a wchar_t to hold > 16 bits, and thus
-// are skipped on Windows, and Cygwin, where a wchar_t is
-// 16-bit wide. This code may not compile on those systems.
-
-// Tests that Unicode code-points that have 17 to 21 bits are encoded
-// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
-TEST(CodePointToUtf8Test, CanEncode17To21Bits) {
- // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
- EXPECT_EQ("\xF0\x90\xA3\x93", CodePointToUtf8(L'\x108D3'));
-
- // 0 0001 0000 0100 0000 0000 => 11110-000 10-010000 10-010000 10-000000
- EXPECT_EQ("\xF0\x90\x90\x80", CodePointToUtf8(L'\x10400'));
-
- // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
- EXPECT_EQ("\xF4\x88\x98\xB4", CodePointToUtf8(L'\x108634'));
-}
-
-// Tests that encoding an invalid code-point generates the expected result.
-TEST(CodePointToUtf8Test, CanEncodeInvalidCodePoint) {
- EXPECT_EQ("(Invalid Unicode 0x1234ABCD)", CodePointToUtf8(L'\x1234ABCD'));
-}
-
-#endif // !GTEST_WIDE_STRING_USES_UTF16_
-
-// Tests WideStringToUtf8().
-
-// Tests that the NUL character L'\0' is encoded correctly.
-TEST(WideStringToUtf8Test, CanEncodeNul) {
- EXPECT_STREQ("", WideStringToUtf8(L"", 0).c_str());
- EXPECT_STREQ("", WideStringToUtf8(L"", -1).c_str());
-}
-
-// Tests that ASCII strings are encoded correctly.
-TEST(WideStringToUtf8Test, CanEncodeAscii) {
- EXPECT_STREQ("a", WideStringToUtf8(L"a", 1).c_str());
- EXPECT_STREQ("ab", WideStringToUtf8(L"ab", 2).c_str());
- EXPECT_STREQ("a", WideStringToUtf8(L"a", -1).c_str());
- EXPECT_STREQ("ab", WideStringToUtf8(L"ab", -1).c_str());
-}
-
-// Tests that Unicode code-points that have 8 to 11 bits are encoded
-// as 110xxxxx 10xxxxxx.
-TEST(WideStringToUtf8Test, CanEncode8To11Bits) {
- // 000 1101 0011 => 110-00011 10-010011
- EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", 1).c_str());
- EXPECT_STREQ("\xC3\x93", WideStringToUtf8(L"\xD3", -1).c_str());
-
- // 101 0111 0110 => 110-10101 10-110110
- const wchar_t s[] = { 0x576, '\0' };
- EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, 1).c_str());
- EXPECT_STREQ("\xD5\xB6", WideStringToUtf8(s, -1).c_str());
-}
-
-// Tests that Unicode code-points that have 12 to 16 bits are encoded
-// as 1110xxxx 10xxxxxx 10xxxxxx.
-TEST(WideStringToUtf8Test, CanEncode12To16Bits) {
- // 0000 1000 1101 0011 => 1110-0000 10-100011 10-010011
- const wchar_t s1[] = { 0x8D3, '\0' };
- EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, 1).c_str());
- EXPECT_STREQ("\xE0\xA3\x93", WideStringToUtf8(s1, -1).c_str());
-
- // 1100 0111 0100 1101 => 1110-1100 10-011101 10-001101
- const wchar_t s2[] = { 0xC74D, '\0' };
- EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, 1).c_str());
- EXPECT_STREQ("\xEC\x9D\x8D", WideStringToUtf8(s2, -1).c_str());
-}
-
-// Tests that the conversion stops when the function encounters \0 character.
-TEST(WideStringToUtf8Test, StopsOnNulCharacter) {
- EXPECT_STREQ("ABC", WideStringToUtf8(L"ABC\0XYZ", 100).c_str());
-}
-
-// Tests that the conversion stops when the function reaches the limit
-// specified by the 'length' parameter.
-TEST(WideStringToUtf8Test, StopsWhenLengthLimitReached) {
- EXPECT_STREQ("ABC", WideStringToUtf8(L"ABCDEF", 3).c_str());
-}
-
-#if !GTEST_WIDE_STRING_USES_UTF16_
-// Tests that Unicode code-points that have 17 to 21 bits are encoded
-// as 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx. This code may not compile
-// on the systems using UTF-16 encoding.
-TEST(WideStringToUtf8Test, CanEncode17To21Bits) {
- // 0 0001 0000 1000 1101 0011 => 11110-000 10-010000 10-100011 10-010011
- EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", 1).c_str());
- EXPECT_STREQ("\xF0\x90\xA3\x93", WideStringToUtf8(L"\x108D3", -1).c_str());
-
- // 1 0000 1000 0110 0011 0100 => 11110-100 10-001000 10-011000 10-110100
- EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", 1).c_str());
- EXPECT_STREQ("\xF4\x88\x98\xB4", WideStringToUtf8(L"\x108634", -1).c_str());
-}
-
-// Tests that encoding an invalid code-point generates the expected result.
-TEST(WideStringToUtf8Test, CanEncodeInvalidCodePoint) {
- EXPECT_STREQ("(Invalid Unicode 0xABCDFF)",
- WideStringToUtf8(L"\xABCDFF", -1).c_str());
-}
-#else // !GTEST_WIDE_STRING_USES_UTF16_
-// Tests that surrogate pairs are encoded correctly on the systems using
-// UTF-16 encoding in the wide strings.
-TEST(WideStringToUtf8Test, CanEncodeValidUtf16SUrrogatePairs) {
- const wchar_t s[] = { 0xD801, 0xDC00, '\0' };
- EXPECT_STREQ("\xF0\x90\x90\x80", WideStringToUtf8(s, -1).c_str());
-}
-
-// Tests that encoding an invalid UTF-16 surrogate pair
-// generates the expected result.
-TEST(WideStringToUtf8Test, CanEncodeInvalidUtf16SurrogatePair) {
- // Leading surrogate is at the end of the string.
- const wchar_t s1[] = { 0xD800, '\0' };
- EXPECT_STREQ("\xED\xA0\x80", WideStringToUtf8(s1, -1).c_str());
- // Leading surrogate is not followed by the trailing surrogate.
- const wchar_t s2[] = { 0xD800, 'M', '\0' };
- EXPECT_STREQ("\xED\xA0\x80M", WideStringToUtf8(s2, -1).c_str());
- // Trailing surrogate appearas without a leading surrogate.
- const wchar_t s3[] = { 0xDC00, 'P', 'Q', 'R', '\0' };
- EXPECT_STREQ("\xED\xB0\x80PQR", WideStringToUtf8(s3, -1).c_str());
-}
-#endif // !GTEST_WIDE_STRING_USES_UTF16_
-
-// Tests that codepoint concatenation works correctly.
-#if !GTEST_WIDE_STRING_USES_UTF16_
-TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
- const wchar_t s[] = { 0x108634, 0xC74D, '\n', 0x576, 0x8D3, 0x108634, '\0'};
- EXPECT_STREQ(
- "\xF4\x88\x98\xB4"
- "\xEC\x9D\x8D"
- "\n"
- "\xD5\xB6"
- "\xE0\xA3\x93"
- "\xF4\x88\x98\xB4",
- WideStringToUtf8(s, -1).c_str());
-}
-#else
-TEST(WideStringToUtf8Test, ConcatenatesCodepointsCorrectly) {
- const wchar_t s[] = { 0xC74D, '\n', 0x576, 0x8D3, '\0'};
- EXPECT_STREQ(
- "\xEC\x9D\x8D" "\n" "\xD5\xB6" "\xE0\xA3\x93",
- WideStringToUtf8(s, -1).c_str());
-}
-#endif // !GTEST_WIDE_STRING_USES_UTF16_
-
-// Tests the Random class.
-
-TEST(RandomDeathTest, GeneratesCrashesOnInvalidRange) {
- testing::internal::Random random(42);
- EXPECT_DEATH_IF_SUPPORTED(
- random.Generate(0),
- "Cannot generate a number in the range \\[0, 0\\)");
- EXPECT_DEATH_IF_SUPPORTED(
- random.Generate(testing::internal::Random::kMaxRange + 1),
- "Generation of a number in \\[0, 2147483649\\) was requested, "
- "but this can only generate numbers in \\[0, 2147483648\\)");
-}
-
-TEST(RandomTest, GeneratesNumbersWithinRange) {
- const UInt32 kRange = 10000;
- testing::internal::Random random(12345);
- for (int i = 0; i < 10; i++) {
- EXPECT_LT(random.Generate(kRange), kRange) << " for iteration " << i;
- }
-
- testing::internal::Random random2(testing::internal::Random::kMaxRange);
- for (int i = 0; i < 10; i++) {
- EXPECT_LT(random2.Generate(kRange), kRange) << " for iteration " << i;
- }
-}
-
-TEST(RandomTest, RepeatsWhenReseeded) {
- const int kSeed = 123;
- const int kArraySize = 10;
- const UInt32 kRange = 10000;
- UInt32 values[kArraySize];
-
- testing::internal::Random random(kSeed);
- for (int i = 0; i < kArraySize; i++) {
- values[i] = random.Generate(kRange);
- }
-
- random.Reseed(kSeed);
- for (int i = 0; i < kArraySize; i++) {
- EXPECT_EQ(values[i], random.Generate(kRange)) << " for iteration " << i;
- }
-}
-
-// Tests STL container utilities.
-
-// Tests CountIf().
-
-static bool IsPositive(int n) { return n > 0; }
-
-TEST(ContainerUtilityTest, CountIf) {
- std::vector<int> v;
- EXPECT_EQ(0, CountIf(v, IsPositive)); // Works for an empty container.
-
- v.push_back(-1);
- v.push_back(0);
- EXPECT_EQ(0, CountIf(v, IsPositive)); // Works when no value satisfies.
-
- v.push_back(2);
- v.push_back(-10);
- v.push_back(10);
- EXPECT_EQ(2, CountIf(v, IsPositive));
-}
-
-// Tests ForEach().
-
-static int g_sum = 0;
-static void Accumulate(int n) { g_sum += n; }
-
-TEST(ContainerUtilityTest, ForEach) {
- std::vector<int> v;
- g_sum = 0;
- ForEach(v, Accumulate);
- EXPECT_EQ(0, g_sum); // Works for an empty container;
-
- g_sum = 0;
- v.push_back(1);
- ForEach(v, Accumulate);
- EXPECT_EQ(1, g_sum); // Works for a container with one element.
-
- g_sum = 0;
- v.push_back(20);
- v.push_back(300);
- ForEach(v, Accumulate);
- EXPECT_EQ(321, g_sum);
-}
-
-// Tests GetElementOr().
-TEST(ContainerUtilityTest, GetElementOr) {
- std::vector<char> a;
- EXPECT_EQ('x', GetElementOr(a, 0, 'x'));
-
- a.push_back('a');
- a.push_back('b');
- EXPECT_EQ('a', GetElementOr(a, 0, 'x'));
- EXPECT_EQ('b', GetElementOr(a, 1, 'x'));
- EXPECT_EQ('x', GetElementOr(a, -2, 'x'));
- EXPECT_EQ('x', GetElementOr(a, 2, 'x'));
-}
-
-TEST(ContainerUtilityDeathTest, ShuffleRange) {
- std::vector<int> a;
- a.push_back(0);
- a.push_back(1);
- a.push_back(2);
- testing::internal::Random random(1);
-
- EXPECT_DEATH_IF_SUPPORTED(
- ShuffleRange(&random, -1, 1, &a),
- "Invalid shuffle range start -1: must be in range \\[0, 3\\]");
- EXPECT_DEATH_IF_SUPPORTED(
- ShuffleRange(&random, 4, 4, &a),
- "Invalid shuffle range start 4: must be in range \\[0, 3\\]");
- EXPECT_DEATH_IF_SUPPORTED(
- ShuffleRange(&random, 3, 2, &a),
- "Invalid shuffle range finish 2: must be in range \\[3, 3\\]");
- EXPECT_DEATH_IF_SUPPORTED(
- ShuffleRange(&random, 3, 4, &a),
- "Invalid shuffle range finish 4: must be in range \\[3, 3\\]");
-}
-
-class VectorShuffleTest : public Test {
- protected:
- static const size_t kVectorSize = 20;
-
- VectorShuffleTest() : random_(1) {
- for (int i = 0; i < static_cast<int>(kVectorSize); i++) {
- vector_.push_back(i);
- }
- }
-
- static bool VectorIsCorrupt(const TestingVector& vector) {
- if (kVectorSize != vector.size()) {
- return true;
- }
-
- bool found_in_vector[kVectorSize] = { false };
- for (size_t i = 0; i < vector.size(); i++) {
- const int e = vector[i];
- if (e < 0 || e >= static_cast<int>(kVectorSize) || found_in_vector[e]) {
- return true;
- }
- found_in_vector[e] = true;
- }
-
- // Vector size is correct, elements' range is correct, no
- // duplicate elements. Therefore no corruption has occurred.
- return false;
- }
-
- static bool VectorIsNotCorrupt(const TestingVector& vector) {
- return !VectorIsCorrupt(vector);
- }
-
- static bool RangeIsShuffled(const TestingVector& vector, int begin, int end) {
- for (int i = begin; i < end; i++) {
- if (i != vector[static_cast<size_t>(i)]) {
- return true;
- }
- }
- return false;
- }
-
- static bool RangeIsUnshuffled(
- const TestingVector& vector, int begin, int end) {
- return !RangeIsShuffled(vector, begin, end);
- }
-
- static bool VectorIsShuffled(const TestingVector& vector) {
- return RangeIsShuffled(vector, 0, static_cast<int>(vector.size()));
- }
-
- static bool VectorIsUnshuffled(const TestingVector& vector) {
- return !VectorIsShuffled(vector);
- }
-
- testing::internal::Random random_;
- TestingVector vector_;
-}; // class VectorShuffleTest
-
-const size_t VectorShuffleTest::kVectorSize;
-
-TEST_F(VectorShuffleTest, HandlesEmptyRange) {
- // Tests an empty range at the beginning...
- ShuffleRange(&random_, 0, 0, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-
- // ...in the middle...
- ShuffleRange(&random_, kVectorSize/2, kVectorSize/2, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-
- // ...at the end...
- ShuffleRange(&random_, kVectorSize - 1, kVectorSize - 1, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-
- // ...and past the end.
- ShuffleRange(&random_, kVectorSize, kVectorSize, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-}
-
-TEST_F(VectorShuffleTest, HandlesRangeOfSizeOne) {
- // Tests a size one range at the beginning...
- ShuffleRange(&random_, 0, 1, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-
- // ...in the middle...
- ShuffleRange(&random_, kVectorSize/2, kVectorSize/2 + 1, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-
- // ...and at the end.
- ShuffleRange(&random_, kVectorSize - 1, kVectorSize, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsUnshuffled, vector_);
-}
-
-// Because we use our own random number generator and a fixed seed,
-// we can guarantee that the following "random" tests will succeed.
-
-TEST_F(VectorShuffleTest, ShufflesEntireVector) {
- Shuffle(&random_, &vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- EXPECT_FALSE(VectorIsUnshuffled(vector_)) << vector_;
-
- // Tests the first and last elements in particular to ensure that
- // there are no off-by-one problems in our shuffle algorithm.
- EXPECT_NE(0, vector_[0]);
- EXPECT_NE(static_cast<int>(kVectorSize - 1), vector_[kVectorSize - 1]);
-}
-
-TEST_F(VectorShuffleTest, ShufflesStartOfVector) {
- const int kRangeSize = kVectorSize/2;
-
- ShuffleRange(&random_, 0, kRangeSize, &vector_);
-
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- EXPECT_PRED3(RangeIsShuffled, vector_, 0, kRangeSize);
- EXPECT_PRED3(RangeIsUnshuffled, vector_, kRangeSize,
- static_cast<int>(kVectorSize));
-}
-
-TEST_F(VectorShuffleTest, ShufflesEndOfVector) {
- const int kRangeSize = kVectorSize / 2;
- ShuffleRange(&random_, kRangeSize, kVectorSize, &vector_);
-
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
- EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize,
- static_cast<int>(kVectorSize));
-}
-
-TEST_F(VectorShuffleTest, ShufflesMiddleOfVector) {
- const int kRangeSize = static_cast<int>(kVectorSize) / 3;
- ShuffleRange(&random_, kRangeSize, 2*kRangeSize, &vector_);
-
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- EXPECT_PRED3(RangeIsUnshuffled, vector_, 0, kRangeSize);
- EXPECT_PRED3(RangeIsShuffled, vector_, kRangeSize, 2*kRangeSize);
- EXPECT_PRED3(RangeIsUnshuffled, vector_, 2 * kRangeSize,
- static_cast<int>(kVectorSize));
-}
-
-TEST_F(VectorShuffleTest, ShufflesRepeatably) {
- TestingVector vector2;
- for (size_t i = 0; i < kVectorSize; i++) {
- vector2.push_back(static_cast<int>(i));
- }
-
- random_.Reseed(1234);
- Shuffle(&random_, &vector_);
- random_.Reseed(1234);
- Shuffle(&random_, &vector2);
-
- ASSERT_PRED1(VectorIsNotCorrupt, vector_);
- ASSERT_PRED1(VectorIsNotCorrupt, vector2);
-
- for (size_t i = 0; i < kVectorSize; i++) {
- EXPECT_EQ(vector_[i], vector2[i]) << " where i is " << i;
- }
-}
-
-// Tests the size of the AssertHelper class.
-
-TEST(AssertHelperTest, AssertHelperIsSmall) {
- // To avoid breaking clients that use lots of assertions in one
- // function, we cannot grow the size of AssertHelper.
- EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
-}
-
-// Tests String::EndsWithCaseInsensitive().
-TEST(StringTest, EndsWithCaseInsensitive) {
- EXPECT_TRUE(String::EndsWithCaseInsensitive("foobar", "BAR"));
- EXPECT_TRUE(String::EndsWithCaseInsensitive("foobaR", "bar"));
- EXPECT_TRUE(String::EndsWithCaseInsensitive("foobar", ""));
- EXPECT_TRUE(String::EndsWithCaseInsensitive("", ""));
-
- EXPECT_FALSE(String::EndsWithCaseInsensitive("Foobar", "foo"));
- EXPECT_FALSE(String::EndsWithCaseInsensitive("foobar", "Foo"));
- EXPECT_FALSE(String::EndsWithCaseInsensitive("", "foo"));
-}
-
-// C++Builder's preprocessor is buggy; it fails to expand macros that
-// appear in macro parameters after wide char literals. Provide an alias
-// for NULL as a workaround.
-static const wchar_t* const kNull = nullptr;
-
-// Tests String::CaseInsensitiveWideCStringEquals
-TEST(StringTest, CaseInsensitiveWideCStringEquals) {
- EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(nullptr, nullptr));
- EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L""));
- EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"", kNull));
- EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(kNull, L"foobar"));
- EXPECT_FALSE(String::CaseInsensitiveWideCStringEquals(L"foobar", kNull));
- EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"foobar"));
- EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"foobar", L"FOOBAR"));
- EXPECT_TRUE(String::CaseInsensitiveWideCStringEquals(L"FOOBAR", L"foobar"));
-}
-
-#if GTEST_OS_WINDOWS
-
-// Tests String::ShowWideCString().
-TEST(StringTest, ShowWideCString) {
- EXPECT_STREQ("(null)",
- String::ShowWideCString(NULL).c_str());
- EXPECT_STREQ("", String::ShowWideCString(L"").c_str());
- EXPECT_STREQ("foo", String::ShowWideCString(L"foo").c_str());
-}
-
-# if GTEST_OS_WINDOWS_MOBILE
-TEST(StringTest, AnsiAndUtf16Null) {
- EXPECT_EQ(NULL, String::AnsiToUtf16(NULL));
- EXPECT_EQ(NULL, String::Utf16ToAnsi(NULL));
-}
-
-TEST(StringTest, AnsiAndUtf16ConvertBasic) {
- const char* ansi = String::Utf16ToAnsi(L"str");
- EXPECT_STREQ("str", ansi);
- delete [] ansi;
- const WCHAR* utf16 = String::AnsiToUtf16("str");
- EXPECT_EQ(0, wcsncmp(L"str", utf16, 3));
- delete [] utf16;
-}
-
-TEST(StringTest, AnsiAndUtf16ConvertPathChars) {
- const char* ansi = String::Utf16ToAnsi(L".:\\ \"*?");
- EXPECT_STREQ(".:\\ \"*?", ansi);
- delete [] ansi;
- const WCHAR* utf16 = String::AnsiToUtf16(".:\\ \"*?");
- EXPECT_EQ(0, wcsncmp(L".:\\ \"*?", utf16, 3));
- delete [] utf16;
-}
-# endif // GTEST_OS_WINDOWS_MOBILE
-
-#endif // GTEST_OS_WINDOWS
-
-// Tests TestProperty construction.
-TEST(TestPropertyTest, StringValue) {
- TestProperty property("key", "1");
- EXPECT_STREQ("key", property.key());
- EXPECT_STREQ("1", property.value());
-}
-
-// Tests TestProperty replacing a value.
-TEST(TestPropertyTest, ReplaceStringValue) {
- TestProperty property("key", "1");
- EXPECT_STREQ("1", property.value());
- property.SetValue("2");
- EXPECT_STREQ("2", property.value());
-}
-
-// AddFatalFailure() and AddNonfatalFailure() must be stand-alone
-// functions (i.e. their definitions cannot be inlined at the call
-// sites), or C++Builder won't compile the code.
-static void AddFatalFailure() {
- FAIL() << "Expected fatal failure.";
-}
-
-static void AddNonfatalFailure() {
- ADD_FAILURE() << "Expected non-fatal failure.";
-}
-
-class ScopedFakeTestPartResultReporterTest : public Test {
- public: // Must be public and not protected due to a bug in g++ 3.4.2.
- enum FailureMode {
- FATAL_FAILURE,
- NONFATAL_FAILURE
- };
- static void AddFailure(FailureMode failure) {
- if (failure == FATAL_FAILURE) {
- AddFatalFailure();
- } else {
- AddNonfatalFailure();
- }
- }
-};
-
-// Tests that ScopedFakeTestPartResultReporter intercepts test
-// failures.
-TEST_F(ScopedFakeTestPartResultReporterTest, InterceptsTestFailures) {
- TestPartResultArray results;
- {
- ScopedFakeTestPartResultReporter reporter(
- ScopedFakeTestPartResultReporter::INTERCEPT_ONLY_CURRENT_THREAD,
- &results);
- AddFailure(NONFATAL_FAILURE);
- AddFailure(FATAL_FAILURE);
- }
-
- EXPECT_EQ(2, results.size());
- EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
- EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
-}
-
-TEST_F(ScopedFakeTestPartResultReporterTest, DeprecatedConstructor) {
- TestPartResultArray results;
- {
- // Tests, that the deprecated constructor still works.
- ScopedFakeTestPartResultReporter reporter(&results);
- AddFailure(NONFATAL_FAILURE);
- }
- EXPECT_EQ(1, results.size());
-}
-
-#if GTEST_IS_THREADSAFE
-
-class ScopedFakeTestPartResultReporterWithThreadsTest
- : public ScopedFakeTestPartResultReporterTest {
- protected:
- static void AddFailureInOtherThread(FailureMode failure) {
- ThreadWithParam<FailureMode> thread(&AddFailure, failure, nullptr);
- thread.Join();
- }
-};
-
-TEST_F(ScopedFakeTestPartResultReporterWithThreadsTest,
- InterceptsTestFailuresInAllThreads) {
- TestPartResultArray results;
- {
- ScopedFakeTestPartResultReporter reporter(
- ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, &results);
- AddFailure(NONFATAL_FAILURE);
- AddFailure(FATAL_FAILURE);
- AddFailureInOtherThread(NONFATAL_FAILURE);
- AddFailureInOtherThread(FATAL_FAILURE);
- }
-
- EXPECT_EQ(4, results.size());
- EXPECT_TRUE(results.GetTestPartResult(0).nonfatally_failed());
- EXPECT_TRUE(results.GetTestPartResult(1).fatally_failed());
- EXPECT_TRUE(results.GetTestPartResult(2).nonfatally_failed());
- EXPECT_TRUE(results.GetTestPartResult(3).fatally_failed());
-}
-
-#endif // GTEST_IS_THREADSAFE
-
-// Tests EXPECT_FATAL_FAILURE{,ON_ALL_THREADS}. Makes sure that they
-// work even if the failure is generated in a called function rather than
-// the current context.
-
-typedef ScopedFakeTestPartResultReporterTest ExpectFatalFailureTest;
-
-TEST_F(ExpectFatalFailureTest, CatchesFatalFaliure) {
- EXPECT_FATAL_FAILURE(AddFatalFailure(), "Expected fatal failure.");
-}
-
-TEST_F(ExpectFatalFailureTest, AcceptsStdStringObject) {
- EXPECT_FATAL_FAILURE(AddFatalFailure(),
- ::std::string("Expected fatal failure."));
-}
-
-TEST_F(ExpectFatalFailureTest, CatchesFatalFailureOnAllThreads) {
- // We have another test below to verify that the macro catches fatal
- // failures generated on another thread.
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFatalFailure(),
- "Expected fatal failure.");
-}
-
-#ifdef __BORLANDC__
-// Silences warnings: "Condition is always true"
-# pragma option push -w-ccc
-#endif
-
-// Tests that EXPECT_FATAL_FAILURE() can be used in a non-void
-// function even when the statement in it contains ASSERT_*.
-
-int NonVoidFunction() {
- EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
- return 0;
-}
-
-TEST_F(ExpectFatalFailureTest, CanBeUsedInNonVoidFunction) {
- NonVoidFunction();
-}
-
-// Tests that EXPECT_FATAL_FAILURE(statement, ...) doesn't abort the
-// current function even though 'statement' generates a fatal failure.
-
-void DoesNotAbortHelper(bool* aborted) {
- EXPECT_FATAL_FAILURE(ASSERT_TRUE(false), "");
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(FAIL(), "");
-
- *aborted = false;
-}
-
-#ifdef __BORLANDC__
-// Restores warnings after previous "#pragma option push" suppressed them.
-# pragma option pop
-#endif
-
-TEST_F(ExpectFatalFailureTest, DoesNotAbort) {
- bool aborted = true;
- DoesNotAbortHelper(&aborted);
- EXPECT_FALSE(aborted);
-}
-
-// Tests that the EXPECT_FATAL_FAILURE{,_ON_ALL_THREADS} accepts a
-// statement that contains a macro which expands to code containing an
-// unprotected comma.
-
-static int global_var = 0;
-#define GTEST_USE_UNPROTECTED_COMMA_ global_var++, global_var++
-
-TEST_F(ExpectFatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
-#ifndef __BORLANDC__
- // ICE's in C++Builder.
- EXPECT_FATAL_FAILURE({
- GTEST_USE_UNPROTECTED_COMMA_;
- AddFatalFailure();
- }, "");
-#endif
-
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS({
- GTEST_USE_UNPROTECTED_COMMA_;
- AddFatalFailure();
- }, "");
-}
-
-// Tests EXPECT_NONFATAL_FAILURE{,ON_ALL_THREADS}.
-
-typedef ScopedFakeTestPartResultReporterTest ExpectNonfatalFailureTest;
-
-TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailure) {
- EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
- "Expected non-fatal failure.");
-}
-
-TEST_F(ExpectNonfatalFailureTest, AcceptsStdStringObject) {
- EXPECT_NONFATAL_FAILURE(AddNonfatalFailure(),
- ::std::string("Expected non-fatal failure."));
-}
-
-TEST_F(ExpectNonfatalFailureTest, CatchesNonfatalFailureOnAllThreads) {
- // We have another test below to verify that the macro catches
- // non-fatal failures generated on another thread.
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(AddNonfatalFailure(),
- "Expected non-fatal failure.");
-}
-
-// Tests that the EXPECT_NONFATAL_FAILURE{,_ON_ALL_THREADS} accepts a
-// statement that contains a macro which expands to code containing an
-// unprotected comma.
-TEST_F(ExpectNonfatalFailureTest, AcceptsMacroThatExpandsToUnprotectedComma) {
- EXPECT_NONFATAL_FAILURE({
- GTEST_USE_UNPROTECTED_COMMA_;
- AddNonfatalFailure();
- }, "");
-
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS({
- GTEST_USE_UNPROTECTED_COMMA_;
- AddNonfatalFailure();
- }, "");
-}
-
-#if GTEST_IS_THREADSAFE
-
-typedef ScopedFakeTestPartResultReporterWithThreadsTest
- ExpectFailureWithThreadsTest;
-
-TEST_F(ExpectFailureWithThreadsTest, ExpectFatalFailureOnAllThreads) {
- EXPECT_FATAL_FAILURE_ON_ALL_THREADS(AddFailureInOtherThread(FATAL_FAILURE),
- "Expected fatal failure.");
-}
-
-TEST_F(ExpectFailureWithThreadsTest, ExpectNonFatalFailureOnAllThreads) {
- EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(
- AddFailureInOtherThread(NONFATAL_FAILURE), "Expected non-fatal failure.");
-}
-
-#endif // GTEST_IS_THREADSAFE
-
-// Tests the TestProperty class.
-
-TEST(TestPropertyTest, ConstructorWorks) {
- const TestProperty property("key", "value");
- EXPECT_STREQ("key", property.key());
- EXPECT_STREQ("value", property.value());
-}
-
-TEST(TestPropertyTest, SetValue) {
- TestProperty property("key", "value_1");
- EXPECT_STREQ("key", property.key());
- property.SetValue("value_2");
- EXPECT_STREQ("key", property.key());
- EXPECT_STREQ("value_2", property.value());
-}
-
-// Tests the TestResult class
-
-// The test fixture for testing TestResult.
-class TestResultTest : public Test {
- protected:
- typedef std::vector<TestPartResult> TPRVector;
-
- // We make use of 2 TestPartResult objects,
- TestPartResult * pr1, * pr2;
-
- // ... and 3 TestResult objects.
- TestResult * r0, * r1, * r2;
-
- void SetUp() override {
- // pr1 is for success.
- pr1 = new TestPartResult(TestPartResult::kSuccess,
- "foo/bar.cc",
- 10,
- "Success!");
-
- // pr2 is for fatal failure.
- pr2 = new TestPartResult(TestPartResult::kFatalFailure,
- "foo/bar.cc",
- -1, // This line number means "unknown"
- "Failure!");
-
- // Creates the TestResult objects.
- r0 = new TestResult();
- r1 = new TestResult();
- r2 = new TestResult();
-
- // In order to test TestResult, we need to modify its internal
- // state, in particular the TestPartResult vector it holds.
- // test_part_results() returns a const reference to this vector.
- // We cast it to a non-const object s.t. it can be modified
- TPRVector* results1 = const_cast<TPRVector*>(
- &TestResultAccessor::test_part_results(*r1));
- TPRVector* results2 = const_cast<TPRVector*>(
- &TestResultAccessor::test_part_results(*r2));
-
- // r0 is an empty TestResult.
-
- // r1 contains a single SUCCESS TestPartResult.
- results1->push_back(*pr1);
-
- // r2 contains a SUCCESS, and a FAILURE.
- results2->push_back(*pr1);
- results2->push_back(*pr2);
- }
-
- void TearDown() override {
- delete pr1;
- delete pr2;
-
- delete r0;
- delete r1;
- delete r2;
- }
-
- // Helper that compares two TestPartResults.
- static void CompareTestPartResult(const TestPartResult& expected,
- const TestPartResult& actual) {
- EXPECT_EQ(expected.type(), actual.type());
- EXPECT_STREQ(expected.file_name(), actual.file_name());
- EXPECT_EQ(expected.line_number(), actual.line_number());
- EXPECT_STREQ(expected.summary(), actual.summary());
- EXPECT_STREQ(expected.message(), actual.message());
- EXPECT_EQ(expected.passed(), actual.passed());
- EXPECT_EQ(expected.failed(), actual.failed());
- EXPECT_EQ(expected.nonfatally_failed(), actual.nonfatally_failed());
- EXPECT_EQ(expected.fatally_failed(), actual.fatally_failed());
- }
-};
-
-// Tests TestResult::total_part_count().
-TEST_F(TestResultTest, total_part_count) {
- ASSERT_EQ(0, r0->total_part_count());
- ASSERT_EQ(1, r1->total_part_count());
- ASSERT_EQ(2, r2->total_part_count());
-}
-
-// Tests TestResult::Passed().
-TEST_F(TestResultTest, Passed) {
- ASSERT_TRUE(r0->Passed());
- ASSERT_TRUE(r1->Passed());
- ASSERT_FALSE(r2->Passed());
-}
-
-// Tests TestResult::Failed().
-TEST_F(TestResultTest, Failed) {
- ASSERT_FALSE(r0->Failed());
- ASSERT_FALSE(r1->Failed());
- ASSERT_TRUE(r2->Failed());
-}
-
-// Tests TestResult::GetTestPartResult().
-
-typedef TestResultTest TestResultDeathTest;
-
-TEST_F(TestResultDeathTest, GetTestPartResult) {
- CompareTestPartResult(*pr1, r2->GetTestPartResult(0));
- CompareTestPartResult(*pr2, r2->GetTestPartResult(1));
- EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(2), "");
- EXPECT_DEATH_IF_SUPPORTED(r2->GetTestPartResult(-1), "");
-}
-
-// Tests TestResult has no properties when none are added.
-TEST(TestResultPropertyTest, NoPropertiesFoundWhenNoneAreAdded) {
- TestResult test_result;
- ASSERT_EQ(0, test_result.test_property_count());
-}
-
-// Tests TestResult has the expected property when added.
-TEST(TestResultPropertyTest, OnePropertyFoundWhenAdded) {
- TestResult test_result;
- TestProperty property("key_1", "1");
- TestResultAccessor::RecordProperty(&test_result, "testcase", property);
- ASSERT_EQ(1, test_result.test_property_count());
- const TestProperty& actual_property = test_result.GetTestProperty(0);
- EXPECT_STREQ("key_1", actual_property.key());
- EXPECT_STREQ("1", actual_property.value());
-}
-
-// Tests TestResult has multiple properties when added.
-TEST(TestResultPropertyTest, MultiplePropertiesFoundWhenAdded) {
- TestResult test_result;
- TestProperty property_1("key_1", "1");
- TestProperty property_2("key_2", "2");
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
- ASSERT_EQ(2, test_result.test_property_count());
- const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
- EXPECT_STREQ("key_1", actual_property_1.key());
- EXPECT_STREQ("1", actual_property_1.value());
-
- const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
- EXPECT_STREQ("key_2", actual_property_2.key());
- EXPECT_STREQ("2", actual_property_2.value());
-}
-
-// Tests TestResult::RecordProperty() overrides values for duplicate keys.
-TEST(TestResultPropertyTest, OverridesValuesForDuplicateKeys) {
- TestResult test_result;
- TestProperty property_1_1("key_1", "1");
- TestProperty property_2_1("key_2", "2");
- TestProperty property_1_2("key_1", "12");
- TestProperty property_2_2("key_2", "22");
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_1);
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_1);
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_1_2);
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_2_2);
-
- ASSERT_EQ(2, test_result.test_property_count());
- const TestProperty& actual_property_1 = test_result.GetTestProperty(0);
- EXPECT_STREQ("key_1", actual_property_1.key());
- EXPECT_STREQ("12", actual_property_1.value());
-
- const TestProperty& actual_property_2 = test_result.GetTestProperty(1);
- EXPECT_STREQ("key_2", actual_property_2.key());
- EXPECT_STREQ("22", actual_property_2.value());
-}
-
-// Tests TestResult::GetTestProperty().
-TEST(TestResultPropertyTest, GetTestProperty) {
- TestResult test_result;
- TestProperty property_1("key_1", "1");
- TestProperty property_2("key_2", "2");
- TestProperty property_3("key_3", "3");
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_1);
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_2);
- TestResultAccessor::RecordProperty(&test_result, "testcase", property_3);
-
- const TestProperty& fetched_property_1 = test_result.GetTestProperty(0);
- const TestProperty& fetched_property_2 = test_result.GetTestProperty(1);
- const TestProperty& fetched_property_3 = test_result.GetTestProperty(2);
-
- EXPECT_STREQ("key_1", fetched_property_1.key());
- EXPECT_STREQ("1", fetched_property_1.value());
-
- EXPECT_STREQ("key_2", fetched_property_2.key());
- EXPECT_STREQ("2", fetched_property_2.value());
-
- EXPECT_STREQ("key_3", fetched_property_3.key());
- EXPECT_STREQ("3", fetched_property_3.value());
-
- EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(3), "");
- EXPECT_DEATH_IF_SUPPORTED(test_result.GetTestProperty(-1), "");
-}
-
-// Tests the Test class.
-//
-// It's difficult to test every public method of this class (we are
-// already stretching the limit of Google Test by using it to test itself!).
-// Fortunately, we don't have to do that, as we are already testing
-// the functionalities of the Test class extensively by using Google Test
-// alone.
-//
-// Therefore, this section only contains one test.
-
-// Tests that GTestFlagSaver works on Windows and Mac.
-
-class GTestFlagSaverTest : public Test {
- protected:
- // Saves the Google Test flags such that we can restore them later, and
- // then sets them to their default values. This will be called
- // before the first test in this test case is run.
- static void SetUpTestSuite() {
- saver_ = new GTestFlagSaver;
-
- GTEST_FLAG(also_run_disabled_tests) = false;
- GTEST_FLAG(break_on_failure) = false;
- GTEST_FLAG(catch_exceptions) = false;
- GTEST_FLAG(death_test_use_fork) = false;
- GTEST_FLAG(color) = "auto";
- GTEST_FLAG(filter) = "";
- GTEST_FLAG(list_tests) = false;
- GTEST_FLAG(output) = "";
- GTEST_FLAG(print_time) = true;
- GTEST_FLAG(random_seed) = 0;
- GTEST_FLAG(repeat) = 1;
- GTEST_FLAG(shuffle) = false;
- GTEST_FLAG(stack_trace_depth) = kMaxStackTraceDepth;
- GTEST_FLAG(stream_result_to) = "";
- GTEST_FLAG(throw_on_failure) = false;
- }
-
- // Restores the Google Test flags that the tests have modified. This will
- // be called after the last test in this test case is run.
- static void TearDownTestSuite() {
- delete saver_;
- saver_ = nullptr;
- }
-
- // Verifies that the Google Test flags have their default values, and then
- // modifies each of them.
- void VerifyAndModifyFlags() {
- EXPECT_FALSE(GTEST_FLAG(also_run_disabled_tests));
- EXPECT_FALSE(GTEST_FLAG(break_on_failure));
- EXPECT_FALSE(GTEST_FLAG(catch_exceptions));
- EXPECT_STREQ("auto", GTEST_FLAG(color).c_str());
- EXPECT_FALSE(GTEST_FLAG(death_test_use_fork));
- EXPECT_STREQ("", GTEST_FLAG(filter).c_str());
- EXPECT_FALSE(GTEST_FLAG(list_tests));
- EXPECT_STREQ("", GTEST_FLAG(output).c_str());
- EXPECT_TRUE(GTEST_FLAG(print_time));
- EXPECT_EQ(0, GTEST_FLAG(random_seed));
- EXPECT_EQ(1, GTEST_FLAG(repeat));
- EXPECT_FALSE(GTEST_FLAG(shuffle));
- EXPECT_EQ(kMaxStackTraceDepth, GTEST_FLAG(stack_trace_depth));
- EXPECT_STREQ("", GTEST_FLAG(stream_result_to).c_str());
- EXPECT_FALSE(GTEST_FLAG(throw_on_failure));
-
- GTEST_FLAG(also_run_disabled_tests) = true;
- GTEST_FLAG(break_on_failure) = true;
- GTEST_FLAG(catch_exceptions) = true;
- GTEST_FLAG(color) = "no";
- GTEST_FLAG(death_test_use_fork) = true;
- GTEST_FLAG(filter) = "abc";
- GTEST_FLAG(list_tests) = true;
- GTEST_FLAG(output) = "xml:foo.xml";
- GTEST_FLAG(print_time) = false;
- GTEST_FLAG(random_seed) = 1;
- GTEST_FLAG(repeat) = 100;
- GTEST_FLAG(shuffle) = true;
- GTEST_FLAG(stack_trace_depth) = 1;
- GTEST_FLAG(stream_result_to) = "localhost:1234";
- GTEST_FLAG(throw_on_failure) = true;
- }
-
- private:
- // For saving Google Test flags during this test case.
- static GTestFlagSaver* saver_;
-};
-
-GTestFlagSaver* GTestFlagSaverTest::saver_ = nullptr;
-
-// Google Test doesn't guarantee the order of tests. The following two
-// tests are designed to work regardless of their order.
-
-// Modifies the Google Test flags in the test body.
-TEST_F(GTestFlagSaverTest, ModifyGTestFlags) {
- VerifyAndModifyFlags();
-}
-
-// Verifies that the Google Test flags in the body of the previous test were
-// restored to their original values.
-TEST_F(GTestFlagSaverTest, VerifyGTestFlags) {
- VerifyAndModifyFlags();
-}
-
-// Sets an environment variable with the given name to the given
-// value. If the value argument is "", unsets the environment
-// variable. The caller must ensure that both arguments are not NULL.
-static void SetEnv(const char* name, const char* value) {
-#if GTEST_OS_WINDOWS_MOBILE
- // Environment variables are not supported on Windows CE.
- return;
-#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
- // C++Builder's putenv only stores a pointer to its parameter; we have to
- // ensure that the string remains valid as long as it might be needed.
- // We use an std::map to do so.
- static std::map<std::string, std::string*> added_env;
-
- // Because putenv stores a pointer to the string buffer, we can't delete the
- // previous string (if present) until after it's replaced.
- std::string *prev_env = NULL;
- if (added_env.find(name) != added_env.end()) {
- prev_env = added_env[name];
- }
- added_env[name] = new std::string(
- (Message() << name << "=" << value).GetString());
-
- // The standard signature of putenv accepts a 'char*' argument. Other
- // implementations, like C++Builder's, accept a 'const char*'.
- // We cast away the 'const' since that would work for both variants.
- putenv(const_cast<char*>(added_env[name]->c_str()));
- delete prev_env;
-#elif GTEST_OS_WINDOWS // If we are on Windows proper.
- _putenv((Message() << name << "=" << value).GetString().c_str());
-#else
- if (*value == '\0') {
- unsetenv(name);
- } else {
- setenv(name, value, 1);
- }
-#endif // GTEST_OS_WINDOWS_MOBILE
-}
-
-#if !GTEST_OS_WINDOWS_MOBILE
-// Environment variables are not supported on Windows CE.
-
-using testing::internal::Int32FromGTestEnv;
-
-// Tests Int32FromGTestEnv().
-
-// Tests that Int32FromGTestEnv() returns the default value when the
-// environment variable is not set.
-TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenVariableIsNotSet) {
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "");
- EXPECT_EQ(10, Int32FromGTestEnv("temp", 10));
-}
-
-# if !defined(GTEST_GET_INT32_FROM_ENV_)
-
-// Tests that Int32FromGTestEnv() returns the default value when the
-// environment variable overflows as an Int32.
-TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueOverflows) {
- printf("(expecting 2 warnings)\n");
-
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12345678987654321");
- EXPECT_EQ(20, Int32FromGTestEnv("temp", 20));
-
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-12345678987654321");
- EXPECT_EQ(30, Int32FromGTestEnv("temp", 30));
-}
-
-// Tests that Int32FromGTestEnv() returns the default value when the
-// environment variable does not represent a valid decimal integer.
-TEST(Int32FromGTestEnvTest, ReturnsDefaultWhenValueIsInvalid) {
- printf("(expecting 2 warnings)\n");
-
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "A1");
- EXPECT_EQ(40, Int32FromGTestEnv("temp", 40));
-
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "12X");
- EXPECT_EQ(50, Int32FromGTestEnv("temp", 50));
-}
-
-# endif // !defined(GTEST_GET_INT32_FROM_ENV_)
-
-// Tests that Int32FromGTestEnv() parses and returns the value of the
-// environment variable when it represents a valid decimal integer in
-// the range of an Int32.
-TEST(Int32FromGTestEnvTest, ParsesAndReturnsValidValue) {
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "123");
- EXPECT_EQ(123, Int32FromGTestEnv("temp", 0));
-
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "TEMP", "-321");
- EXPECT_EQ(-321, Int32FromGTestEnv("temp", 0));
-}
-#endif // !GTEST_OS_WINDOWS_MOBILE
-
-// Tests ParseInt32Flag().
-
-// Tests that ParseInt32Flag() returns false and doesn't change the
-// output value when the flag has wrong format
-TEST(ParseInt32FlagTest, ReturnsFalseForInvalidFlag) {
- Int32 value = 123;
- EXPECT_FALSE(ParseInt32Flag("--a=100", "b", &value));
- EXPECT_EQ(123, value);
-
- EXPECT_FALSE(ParseInt32Flag("a=100", "a", &value));
- EXPECT_EQ(123, value);
-}
-
-// Tests that ParseInt32Flag() returns false and doesn't change the
-// output value when the flag overflows as an Int32.
-TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueOverflows) {
- printf("(expecting 2 warnings)\n");
-
- Int32 value = 123;
- EXPECT_FALSE(ParseInt32Flag("--abc=12345678987654321", "abc", &value));
- EXPECT_EQ(123, value);
-
- EXPECT_FALSE(ParseInt32Flag("--abc=-12345678987654321", "abc", &value));
- EXPECT_EQ(123, value);
-}
-
-// Tests that ParseInt32Flag() returns false and doesn't change the
-// output value when the flag does not represent a valid decimal
-// integer.
-TEST(ParseInt32FlagTest, ReturnsDefaultWhenValueIsInvalid) {
- printf("(expecting 2 warnings)\n");
-
- Int32 value = 123;
- EXPECT_FALSE(ParseInt32Flag("--abc=A1", "abc", &value));
- EXPECT_EQ(123, value);
-
- EXPECT_FALSE(ParseInt32Flag("--abc=12X", "abc", &value));
- EXPECT_EQ(123, value);
-}
-
-// Tests that ParseInt32Flag() parses the value of the flag and
-// returns true when the flag represents a valid decimal integer in
-// the range of an Int32.
-TEST(ParseInt32FlagTest, ParsesAndReturnsValidValue) {
- Int32 value = 123;
- EXPECT_TRUE(ParseInt32Flag("--" GTEST_FLAG_PREFIX_ "abc=456", "abc", &value));
- EXPECT_EQ(456, value);
-
- EXPECT_TRUE(ParseInt32Flag("--" GTEST_FLAG_PREFIX_ "abc=-789",
- "abc", &value));
- EXPECT_EQ(-789, value);
-}
-
-// Tests that Int32FromEnvOrDie() parses the value of the var or
-// returns the correct default.
-// Environment variables are not supported on Windows CE.
-#if !GTEST_OS_WINDOWS_MOBILE
-TEST(Int32FromEnvOrDieTest, ParsesAndReturnsValidValue) {
- EXPECT_EQ(333, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "123");
- EXPECT_EQ(123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", "-123");
- EXPECT_EQ(-123, Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "UnsetVar", 333));
-}
-#endif // !GTEST_OS_WINDOWS_MOBILE
-
-// Tests that Int32FromEnvOrDie() aborts with an error message
-// if the variable is not an Int32.
-TEST(Int32FromEnvOrDieDeathTest, AbortsOnFailure) {
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "xxx");
- EXPECT_DEATH_IF_SUPPORTED(
- Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
- ".*");
-}
-
-// Tests that Int32FromEnvOrDie() aborts with an error message
-// if the variable cannot be represented by an Int32.
-TEST(Int32FromEnvOrDieDeathTest, AbortsOnInt32Overflow) {
- SetEnv(GTEST_FLAG_PREFIX_UPPER_ "VAR", "1234567891234567891234");
- EXPECT_DEATH_IF_SUPPORTED(
- Int32FromEnvOrDie(GTEST_FLAG_PREFIX_UPPER_ "VAR", 123),
- ".*");
-}
-
-// Tests that ShouldRunTestOnShard() selects all tests
-// where there is 1 shard.
-TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereIsOneShard) {
- EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 0));
- EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 1));
- EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 2));
- EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 3));
- EXPECT_TRUE(ShouldRunTestOnShard(1, 0, 4));
-}
-
-class ShouldShardTest : public testing::Test {
- protected:
- void SetUp() override {
- index_var_ = GTEST_FLAG_PREFIX_UPPER_ "INDEX";
- total_var_ = GTEST_FLAG_PREFIX_UPPER_ "TOTAL";
- }
-
- void TearDown() override {
- SetEnv(index_var_, "");
- SetEnv(total_var_, "");
- }
-
- const char* index_var_;
- const char* total_var_;
-};
-
-// Tests that sharding is disabled if neither of the environment variables
-// are set.
-TEST_F(ShouldShardTest, ReturnsFalseWhenNeitherEnvVarIsSet) {
- SetEnv(index_var_, "");
- SetEnv(total_var_, "");
-
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
-}
-
-// Tests that sharding is not enabled if total_shards == 1.
-TEST_F(ShouldShardTest, ReturnsFalseWhenTotalShardIsOne) {
- SetEnv(index_var_, "0");
- SetEnv(total_var_, "1");
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, false));
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
-}
-
-// Tests that sharding is enabled if total_shards > 1 and
-// we are not in a death test subprocess.
-// Environment variables are not supported on Windows CE.
-#if !GTEST_OS_WINDOWS_MOBILE
-TEST_F(ShouldShardTest, WorksWhenShardEnvVarsAreValid) {
- SetEnv(index_var_, "4");
- SetEnv(total_var_, "22");
- EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
-
- SetEnv(index_var_, "8");
- SetEnv(total_var_, "9");
- EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
-
- SetEnv(index_var_, "0");
- SetEnv(total_var_, "9");
- EXPECT_TRUE(ShouldShard(total_var_, index_var_, false));
- EXPECT_FALSE(ShouldShard(total_var_, index_var_, true));
-}
-#endif // !GTEST_OS_WINDOWS_MOBILE
-
-// Tests that we exit in error if the sharding values are not valid.
-
-typedef ShouldShardTest ShouldShardDeathTest;
-
-TEST_F(ShouldShardDeathTest, AbortsWhenShardingEnvVarsAreInvalid) {
- SetEnv(index_var_, "4");
- SetEnv(total_var_, "4");
- EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
-
- SetEnv(index_var_, "4");
- SetEnv(total_var_, "-2");
- EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
-
- SetEnv(index_var_, "5");
- SetEnv(total_var_, "");
- EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
-
- SetEnv(index_var_, "");
- SetEnv(total_var_, "5");
- EXPECT_DEATH_IF_SUPPORTED(ShouldShard(total_var_, index_var_, false), ".*");
-}
-
-// Tests that ShouldRunTestOnShard is a partition when 5
-// shards are used.
-TEST(ShouldRunTestOnShardTest, IsPartitionWhenThereAreFiveShards) {
- // Choose an arbitrary number of tests and shards.
- const int num_tests = 17;
- const int num_shards = 5;
-
- // Check partitioning: each test should be on exactly 1 shard.
- for (int test_id = 0; test_id < num_tests; test_id++) {
- int prev_selected_shard_index = -1;
- for (int shard_index = 0; shard_index < num_shards; shard_index++) {
- if (ShouldRunTestOnShard(num_shards, shard_index, test_id)) {
- if (prev_selected_shard_index < 0) {
- prev_selected_shard_index = shard_index;
- } else {
- ADD_FAILURE() << "Shard " << prev_selected_shard_index << " and "
- << shard_index << " are both selected to run test " << test_id;
- }
- }
- }
- }
-
- // Check balance: This is not required by the sharding protocol, but is a
- // desirable property for performance.
- for (int shard_index = 0; shard_index < num_shards; shard_index++) {
- int num_tests_on_shard = 0;
- for (int test_id = 0; test_id < num_tests; test_id++) {
- num_tests_on_shard +=
- ShouldRunTestOnShard(num_shards, shard_index, test_id);
- }
- EXPECT_GE(num_tests_on_shard, num_tests / num_shards);
- }
-}
-
-// For the same reason we are not explicitly testing everything in the
-// Test class, there are no separate tests for the following classes
-// (except for some trivial cases):
-//
-// TestSuite, UnitTest, UnitTestResultPrinter.
-//
-// Similarly, there are no separate tests for the following macros:
-//
-// TEST, TEST_F, RUN_ALL_TESTS
-
-TEST(UnitTestTest, CanGetOriginalWorkingDir) {
- ASSERT_TRUE(UnitTest::GetInstance()->original_working_dir() != nullptr);
- EXPECT_STRNE(UnitTest::GetInstance()->original_working_dir(), "");
-}
-
-TEST(UnitTestTest, ReturnsPlausibleTimestamp) {
- EXPECT_LT(0, UnitTest::GetInstance()->start_timestamp());
- EXPECT_LE(UnitTest::GetInstance()->start_timestamp(), GetTimeInMillis());
-}
-
-// When a property using a reserved key is supplied to this function, it
-// tests that a non-fatal failure is added, a fatal failure is not added,
-// and that the property is not recorded.
-void ExpectNonFatalFailureRecordingPropertyWithReservedKey(
- const TestResult& test_result, const char* key) {
- EXPECT_NONFATAL_FAILURE(Test::RecordProperty(key, "1"), "Reserved key");
- ASSERT_EQ(0, test_result.test_property_count()) << "Property for key '" << key
- << "' recorded unexpectedly.";
-}
-
-void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- const char* key) {
- const TestInfo* test_info = UnitTest::GetInstance()->current_test_info();
- ASSERT_TRUE(test_info != nullptr);
- ExpectNonFatalFailureRecordingPropertyWithReservedKey(*test_info->result(),
- key);
-}
-
-void ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- const char* key) {
- const testing::TestSuite* test_suite =
- UnitTest::GetInstance()->current_test_suite();
- ASSERT_TRUE(test_suite != nullptr);
- ExpectNonFatalFailureRecordingPropertyWithReservedKey(
- test_suite->ad_hoc_test_result(), key);
-}
-
-void ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- const char* key) {
- ExpectNonFatalFailureRecordingPropertyWithReservedKey(
- UnitTest::GetInstance()->ad_hoc_test_result(), key);
-}
-
-// Tests that property recording functions in UnitTest outside of tests
-// functions correcly. Creating a separate instance of UnitTest ensures it
-// is in a state similar to the UnitTest's singleton's between tests.
-class UnitTestRecordPropertyTest :
- public testing::internal::UnitTestRecordPropertyTestHelper {
- public:
- static void SetUpTestSuite() {
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- "disabled");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- "errors");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- "failures");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- "name");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- "tests");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTestSuite(
- "time");
-
- Test::RecordProperty("test_case_key_1", "1");
-
- const testing::TestSuite* test_suite =
- UnitTest::GetInstance()->current_test_suite();
-
- ASSERT_TRUE(test_suite != nullptr);
-
- ASSERT_EQ(1, test_suite->ad_hoc_test_result().test_property_count());
- EXPECT_STREQ("test_case_key_1",
- test_suite->ad_hoc_test_result().GetTestProperty(0).key());
- EXPECT_STREQ("1",
- test_suite->ad_hoc_test_result().GetTestProperty(0).value());
- }
-};
-
-// Tests TestResult has the expected property when added.
-TEST_F(UnitTestRecordPropertyTest, OnePropertyFoundWhenAdded) {
- UnitTestRecordProperty("key_1", "1");
-
- ASSERT_EQ(1, unit_test_.ad_hoc_test_result().test_property_count());
-
- EXPECT_STREQ("key_1",
- unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
- EXPECT_STREQ("1",
- unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
-}
-
-// Tests TestResult has multiple properties when added.
-TEST_F(UnitTestRecordPropertyTest, MultiplePropertiesFoundWhenAdded) {
- UnitTestRecordProperty("key_1", "1");
- UnitTestRecordProperty("key_2", "2");
-
- ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
-
- EXPECT_STREQ("key_1",
- unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
- EXPECT_STREQ("1", unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
-
- EXPECT_STREQ("key_2",
- unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
- EXPECT_STREQ("2", unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
-}
-
-// Tests TestResult::RecordProperty() overrides values for duplicate keys.
-TEST_F(UnitTestRecordPropertyTest, OverridesValuesForDuplicateKeys) {
- UnitTestRecordProperty("key_1", "1");
- UnitTestRecordProperty("key_2", "2");
- UnitTestRecordProperty("key_1", "12");
- UnitTestRecordProperty("key_2", "22");
-
- ASSERT_EQ(2, unit_test_.ad_hoc_test_result().test_property_count());
-
- EXPECT_STREQ("key_1",
- unit_test_.ad_hoc_test_result().GetTestProperty(0).key());
- EXPECT_STREQ("12",
- unit_test_.ad_hoc_test_result().GetTestProperty(0).value());
-
- EXPECT_STREQ("key_2",
- unit_test_.ad_hoc_test_result().GetTestProperty(1).key());
- EXPECT_STREQ("22",
- unit_test_.ad_hoc_test_result().GetTestProperty(1).value());
-}
-
-TEST_F(UnitTestRecordPropertyTest,
- AddFailureInsideTestsWhenUsingTestSuiteReservedKeys) {
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- "name");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- "value_param");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- "type_param");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- "status");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- "time");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyForCurrentTest(
- "classname");
-}
-
-TEST_F(UnitTestRecordPropertyTest,
- AddRecordWithReservedKeysGeneratesCorrectPropertyList) {
- EXPECT_NONFATAL_FAILURE(
- Test::RecordProperty("name", "1"),
- "'classname', 'name', 'status', 'time', 'type_param', 'value_param',"
- " 'file', and 'line' are reserved");
-}
-
-class UnitTestRecordPropertyTestEnvironment : public Environment {
- public:
- void TearDown() override {
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "tests");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "failures");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "disabled");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "errors");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "name");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "timestamp");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "time");
- ExpectNonFatalFailureRecordingPropertyWithReservedKeyOutsideOfTestSuite(
- "random_seed");
- }
-};
-
-// This will test property recording outside of any test or test case.
-static Environment* record_property_env GTEST_ATTRIBUTE_UNUSED_ =
- AddGlobalTestEnvironment(new UnitTestRecordPropertyTestEnvironment);
-
-// This group of tests is for predicate assertions (ASSERT_PRED*, etc)
-// of various arities. They do not attempt to be exhaustive. Rather,
-// view them as smoke tests that can be easily reviewed and verified.
-// A more complete set of tests for predicate assertions can be found
-// in gtest_pred_impl_unittest.cc.
-
-// First, some predicates and predicate-formatters needed by the tests.
-
-// Returns true if and only if the argument is an even number.
-bool IsEven(int n) {
- return (n % 2) == 0;
-}
-
-// A functor that returns true if and only if the argument is an even number.
-struct IsEvenFunctor {
- bool operator()(int n) { return IsEven(n); }
-};
-
-// A predicate-formatter function that asserts the argument is an even
-// number.
-AssertionResult AssertIsEven(const char* expr, int n) {
- if (IsEven(n)) {
- return AssertionSuccess();
- }
-
- Message msg;
- msg << expr << " evaluates to " << n << ", which is not even.";
- return AssertionFailure(msg);
-}
-
-// A predicate function that returns AssertionResult for use in
-// EXPECT/ASSERT_TRUE/FALSE.
-AssertionResult ResultIsEven(int n) {
- if (IsEven(n))
- return AssertionSuccess() << n << " is even";
- else
- return AssertionFailure() << n << " is odd";
-}
-
-// A predicate function that returns AssertionResult but gives no
-// explanation why it succeeds. Needed for testing that
-// EXPECT/ASSERT_FALSE handles such functions correctly.
-AssertionResult ResultIsEvenNoExplanation(int n) {
- if (IsEven(n))
- return AssertionSuccess();
- else
- return AssertionFailure() << n << " is odd";
-}
-
-// A predicate-formatter functor that asserts the argument is an even
-// number.
-struct AssertIsEvenFunctor {
- AssertionResult operator()(const char* expr, int n) {
- return AssertIsEven(expr, n);
- }
-};
-
-// Returns true if and only if the sum of the arguments is an even number.
-bool SumIsEven2(int n1, int n2) {
- return IsEven(n1 + n2);
-}
-
-// A functor that returns true if and only if the sum of the arguments is an
-// even number.
-struct SumIsEven3Functor {
- bool operator()(int n1, int n2, int n3) {
- return IsEven(n1 + n2 + n3);
- }
-};
-
-// A predicate-formatter function that asserts the sum of the
-// arguments is an even number.
-AssertionResult AssertSumIsEven4(
- const char* e1, const char* e2, const char* e3, const char* e4,
- int n1, int n2, int n3, int n4) {
- const int sum = n1 + n2 + n3 + n4;
- if (IsEven(sum)) {
- return AssertionSuccess();
- }
-
- Message msg;
- msg << e1 << " + " << e2 << " + " << e3 << " + " << e4
- << " (" << n1 << " + " << n2 << " + " << n3 << " + " << n4
- << ") evaluates to " << sum << ", which is not even.";
- return AssertionFailure(msg);
-}
-
-// A predicate-formatter functor that asserts the sum of the arguments
-// is an even number.
-struct AssertSumIsEven5Functor {
- AssertionResult operator()(
- const char* e1, const char* e2, const char* e3, const char* e4,
- const char* e5, int n1, int n2, int n3, int n4, int n5) {
- const int sum = n1 + n2 + n3 + n4 + n5;
- if (IsEven(sum)) {
- return AssertionSuccess();
- }
-
- Message msg;
- msg << e1 << " + " << e2 << " + " << e3 << " + " << e4 << " + " << e5
- << " ("
- << n1 << " + " << n2 << " + " << n3 << " + " << n4 << " + " << n5
- << ") evaluates to " << sum << ", which is not even.";
- return AssertionFailure(msg);
- }
-};
-
-
-// Tests unary predicate assertions.
-
-// Tests unary predicate assertions that don't use a custom formatter.
-TEST(Pred1Test, WithoutFormat) {
- // Success cases.
- EXPECT_PRED1(IsEvenFunctor(), 2) << "This failure is UNEXPECTED!";
- ASSERT_PRED1(IsEven, 4);
-
- // Failure cases.
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED1(IsEven, 5) << "This failure is expected.";
- }, "This failure is expected.");
- EXPECT_FATAL_FAILURE(ASSERT_PRED1(IsEvenFunctor(), 5),
- "evaluates to false");
-}
-
-// Tests unary predicate assertions that use a custom formatter.
-TEST(Pred1Test, WithFormat) {
- // Success cases.
- EXPECT_PRED_FORMAT1(AssertIsEven, 2);
- ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), 4)
- << "This failure is UNEXPECTED!";
-
- // Failure cases.
- const int n = 5;
- EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT1(AssertIsEvenFunctor(), n),
- "n evaluates to 5, which is not even.");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT1(AssertIsEven, 5) << "This failure is expected.";
- }, "This failure is expected.");
-}
-
-// Tests that unary predicate assertions evaluates their arguments
-// exactly once.
-TEST(Pred1Test, SingleEvaluationOnFailure) {
- // A success case.
- static int n = 0;
- EXPECT_PRED1(IsEven, n++);
- EXPECT_EQ(1, n) << "The argument is not evaluated exactly once.";
-
- // A failure case.
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT1(AssertIsEvenFunctor(), n++)
- << "This failure is expected.";
- }, "This failure is expected.");
- EXPECT_EQ(2, n) << "The argument is not evaluated exactly once.";
-}
-
-
-// Tests predicate assertions whose arity is >= 2.
-
-// Tests predicate assertions that don't use a custom formatter.
-TEST(PredTest, WithoutFormat) {
- // Success cases.
- ASSERT_PRED2(SumIsEven2, 2, 4) << "This failure is UNEXPECTED!";
- EXPECT_PRED3(SumIsEven3Functor(), 4, 6, 8);
-
- // Failure cases.
- const int n1 = 1;
- const int n2 = 2;
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED2(SumIsEven2, n1, n2) << "This failure is expected.";
- }, "This failure is expected.");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED3(SumIsEven3Functor(), 1, 2, 4);
- }, "evaluates to false");
-}
-
-// Tests predicate assertions that use a custom formatter.
-TEST(PredTest, WithFormat) {
- // Success cases.
- ASSERT_PRED_FORMAT4(AssertSumIsEven4, 4, 6, 8, 10) <<
- "This failure is UNEXPECTED!";
- EXPECT_PRED_FORMAT5(AssertSumIsEven5Functor(), 2, 4, 6, 8, 10);
-
- // Failure cases.
- const int n1 = 1;
- const int n2 = 2;
- const int n3 = 4;
- const int n4 = 6;
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT4(AssertSumIsEven4, n1, n2, n3, n4);
- }, "evaluates to 13, which is not even.");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(), 1, 2, 4, 6, 8)
- << "This failure is expected.";
- }, "This failure is expected.");
-}
-
-// Tests that predicate assertions evaluates their arguments
-// exactly once.
-TEST(PredTest, SingleEvaluationOnFailure) {
- // A success case.
- int n1 = 0;
- int n2 = 0;
- EXPECT_PRED2(SumIsEven2, n1++, n2++);
- EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
- EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
-
- // Another success case.
- n1 = n2 = 0;
- int n3 = 0;
- int n4 = 0;
- int n5 = 0;
- ASSERT_PRED_FORMAT5(AssertSumIsEven5Functor(),
- n1++, n2++, n3++, n4++, n5++)
- << "This failure is UNEXPECTED!";
- EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
- EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
- EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
- EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
- EXPECT_EQ(1, n5) << "Argument 5 is not evaluated exactly once.";
-
- // A failure case.
- n1 = n2 = n3 = 0;
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED3(SumIsEven3Functor(), ++n1, n2++, n3++)
- << "This failure is expected.";
- }, "This failure is expected.");
- EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
- EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
- EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
-
- // Another failure case.
- n1 = n2 = n3 = n4 = 0;
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT4(AssertSumIsEven4, ++n1, n2++, n3++, n4++);
- }, "evaluates to 1, which is not even.");
- EXPECT_EQ(1, n1) << "Argument 1 is not evaluated exactly once.";
- EXPECT_EQ(1, n2) << "Argument 2 is not evaluated exactly once.";
- EXPECT_EQ(1, n3) << "Argument 3 is not evaluated exactly once.";
- EXPECT_EQ(1, n4) << "Argument 4 is not evaluated exactly once.";
-}
-
-// Test predicate assertions for sets
-TEST(PredTest, ExpectPredEvalFailure) {
- std::set<int> set_a = {2, 1, 3, 4, 5};
- std::set<int> set_b = {0, 4, 8};
- const auto compare_sets = [] (std::set<int>, std::set<int>) { return false; };
- EXPECT_NONFATAL_FAILURE(
- EXPECT_PRED2(compare_sets, set_a, set_b),
- "compare_sets(set_a, set_b) evaluates to false, where\nset_a evaluates "
- "to { 1, 2, 3, 4, 5 }\nset_b evaluates to { 0, 4, 8 }");
-}
-
-// Some helper functions for testing using overloaded/template
-// functions with ASSERT_PREDn and EXPECT_PREDn.
-
-bool IsPositive(double x) {
- return x > 0;
-}
-
-template <typename T>
-bool IsNegative(T x) {
- return x < 0;
-}
-
-template <typename T1, typename T2>
-bool GreaterThan(T1 x1, T2 x2) {
- return x1 > x2;
-}
-
-// Tests that overloaded functions can be used in *_PRED* as long as
-// their types are explicitly specified.
-TEST(PredicateAssertionTest, AcceptsOverloadedFunction) {
- // C++Builder requires C-style casts rather than static_cast.
- EXPECT_PRED1((bool (*)(int))(IsPositive), 5); // NOLINT
- ASSERT_PRED1((bool (*)(double))(IsPositive), 6.0); // NOLINT
-}
-
-// Tests that template functions can be used in *_PRED* as long as
-// their types are explicitly specified.
-TEST(PredicateAssertionTest, AcceptsTemplateFunction) {
- EXPECT_PRED1(IsNegative<int>, -5);
- // Makes sure that we can handle templates with more than one
- // parameter.
- ASSERT_PRED2((GreaterThan<int, int>), 5, 0);
-}
-
-
-// Some helper functions for testing using overloaded/template
-// functions with ASSERT_PRED_FORMATn and EXPECT_PRED_FORMATn.
-
-AssertionResult IsPositiveFormat(const char* /* expr */, int n) {
- return n > 0 ? AssertionSuccess() :
- AssertionFailure(Message() << "Failure");
-}
-
-AssertionResult IsPositiveFormat(const char* /* expr */, double x) {
- return x > 0 ? AssertionSuccess() :
- AssertionFailure(Message() << "Failure");
-}
-
-template <typename T>
-AssertionResult IsNegativeFormat(const char* /* expr */, T x) {
- return x < 0 ? AssertionSuccess() :
- AssertionFailure(Message() << "Failure");
-}
-
-template <typename T1, typename T2>
-AssertionResult EqualsFormat(const char* /* expr1 */, const char* /* expr2 */,
- const T1& x1, const T2& x2) {
- return x1 == x2 ? AssertionSuccess() :
- AssertionFailure(Message() << "Failure");
-}
-
-// Tests that overloaded functions can be used in *_PRED_FORMAT*
-// without explicitly specifying their types.
-TEST(PredicateFormatAssertionTest, AcceptsOverloadedFunction) {
- EXPECT_PRED_FORMAT1(IsPositiveFormat, 5);
- ASSERT_PRED_FORMAT1(IsPositiveFormat, 6.0);
-}
-
-// Tests that template functions can be used in *_PRED_FORMAT* without
-// explicitly specifying their types.
-TEST(PredicateFormatAssertionTest, AcceptsTemplateFunction) {
- EXPECT_PRED_FORMAT1(IsNegativeFormat, -5);
- ASSERT_PRED_FORMAT2(EqualsFormat, 3, 3);
-}
-
-
-// Tests string assertions.
-
-// Tests ASSERT_STREQ with non-NULL arguments.
-TEST(StringAssertionTest, ASSERT_STREQ) {
- const char * const p1 = "good";
- ASSERT_STREQ(p1, p1);
-
- // Let p2 have the same content as p1, but be at a different address.
- const char p2[] = "good";
- ASSERT_STREQ(p1, p2);
-
- EXPECT_FATAL_FAILURE(ASSERT_STREQ("bad", "good"),
- " \"bad\"\n \"good\"");
-}
-
-// Tests ASSERT_STREQ with NULL arguments.
-TEST(StringAssertionTest, ASSERT_STREQ_Null) {
- ASSERT_STREQ(static_cast<const char*>(nullptr), nullptr);
- EXPECT_FATAL_FAILURE(ASSERT_STREQ(nullptr, "non-null"), "non-null");
-}
-
-// Tests ASSERT_STREQ with NULL arguments.
-TEST(StringAssertionTest, ASSERT_STREQ_Null2) {
- EXPECT_FATAL_FAILURE(ASSERT_STREQ("non-null", nullptr), "non-null");
-}
-
-// Tests ASSERT_STRNE.
-TEST(StringAssertionTest, ASSERT_STRNE) {
- ASSERT_STRNE("hi", "Hi");
- ASSERT_STRNE("Hi", nullptr);
- ASSERT_STRNE(nullptr, "Hi");
- ASSERT_STRNE("", nullptr);
- ASSERT_STRNE(nullptr, "");
- ASSERT_STRNE("", "Hi");
- ASSERT_STRNE("Hi", "");
- EXPECT_FATAL_FAILURE(ASSERT_STRNE("Hi", "Hi"),
- "\"Hi\" vs \"Hi\"");
-}
-
-// Tests ASSERT_STRCASEEQ.
-TEST(StringAssertionTest, ASSERT_STRCASEEQ) {
- ASSERT_STRCASEEQ("hi", "Hi");
- ASSERT_STRCASEEQ(static_cast<const char*>(nullptr), nullptr);
-
- ASSERT_STRCASEEQ("", "");
- EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("Hi", "hi2"),
- "Ignoring case");
-}
-
-// Tests ASSERT_STRCASENE.
-TEST(StringAssertionTest, ASSERT_STRCASENE) {
- ASSERT_STRCASENE("hi1", "Hi2");
- ASSERT_STRCASENE("Hi", nullptr);
- ASSERT_STRCASENE(nullptr, "Hi");
- ASSERT_STRCASENE("", nullptr);
- ASSERT_STRCASENE(nullptr, "");
- ASSERT_STRCASENE("", "Hi");
- ASSERT_STRCASENE("Hi", "");
- EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("Hi", "hi"),
- "(ignoring case)");
-}
-
-// Tests *_STREQ on wide strings.
-TEST(StringAssertionTest, STREQ_Wide) {
- // NULL strings.
- ASSERT_STREQ(static_cast<const wchar_t*>(nullptr), nullptr);
-
- // Empty strings.
- ASSERT_STREQ(L"", L"");
-
- // Non-null vs NULL.
- EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"non-null", nullptr), "non-null");
-
- // Equal strings.
- EXPECT_STREQ(L"Hi", L"Hi");
-
- // Unequal strings.
- EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc", L"Abc"),
- "Abc");
-
- // Strings containing wide characters.
- EXPECT_NONFATAL_FAILURE(EXPECT_STREQ(L"abc\x8119", L"abc\x8120"),
- "abc");
-
- // The streaming variation.
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_STREQ(L"abc\x8119", L"abc\x8121") << "Expected failure";
- }, "Expected failure");
-}
-
-// Tests *_STRNE on wide strings.
-TEST(StringAssertionTest, STRNE_Wide) {
- // NULL strings.
- EXPECT_NONFATAL_FAILURE(
- { // NOLINT
- EXPECT_STRNE(static_cast<const wchar_t*>(nullptr), nullptr);
- },
- "");
-
- // Empty strings.
- EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"", L""),
- "L\"\"");
-
- // Non-null vs NULL.
- ASSERT_STRNE(L"non-null", nullptr);
-
- // Equal strings.
- EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"Hi", L"Hi"),
- "L\"Hi\"");
-
- // Unequal strings.
- EXPECT_STRNE(L"abc", L"Abc");
-
- // Strings containing wide characters.
- EXPECT_NONFATAL_FAILURE(EXPECT_STRNE(L"abc\x8119", L"abc\x8119"),
- "abc");
-
- // The streaming variation.
- ASSERT_STRNE(L"abc\x8119", L"abc\x8120") << "This shouldn't happen";
-}
-
-// Tests for ::testing::IsSubstring().
-
-// Tests that IsSubstring() returns the correct result when the input
-// argument type is const char*.
-TEST(IsSubstringTest, ReturnsCorrectResultForCString) {
- EXPECT_FALSE(IsSubstring("", "", nullptr, "a"));
- EXPECT_FALSE(IsSubstring("", "", "b", nullptr));
- EXPECT_FALSE(IsSubstring("", "", "needle", "haystack"));
-
- EXPECT_TRUE(IsSubstring("", "", static_cast<const char*>(nullptr), nullptr));
- EXPECT_TRUE(IsSubstring("", "", "needle", "two needles"));
-}
-
-// Tests that IsSubstring() returns the correct result when the input
-// argument type is const wchar_t*.
-TEST(IsSubstringTest, ReturnsCorrectResultForWideCString) {
- EXPECT_FALSE(IsSubstring("", "", kNull, L"a"));
- EXPECT_FALSE(IsSubstring("", "", L"b", kNull));
- EXPECT_FALSE(IsSubstring("", "", L"needle", L"haystack"));
-
- EXPECT_TRUE(
- IsSubstring("", "", static_cast<const wchar_t*>(nullptr), nullptr));
- EXPECT_TRUE(IsSubstring("", "", L"needle", L"two needles"));
-}
-
-// Tests that IsSubstring() generates the correct message when the input
-// argument type is const char*.
-TEST(IsSubstringTest, GeneratesCorrectMessageForCString) {
- EXPECT_STREQ("Value of: needle_expr\n"
- " Actual: \"needle\"\n"
- "Expected: a substring of haystack_expr\n"
- "Which is: \"haystack\"",
- IsSubstring("needle_expr", "haystack_expr",
- "needle", "haystack").failure_message());
-}
-
-// Tests that IsSubstring returns the correct result when the input
-// argument type is ::std::string.
-TEST(IsSubstringTest, ReturnsCorrectResultsForStdString) {
- EXPECT_TRUE(IsSubstring("", "", std::string("hello"), "ahellob"));
- EXPECT_FALSE(IsSubstring("", "", "hello", std::string("world")));
-}
-
-#if GTEST_HAS_STD_WSTRING
-// Tests that IsSubstring returns the correct result when the input
-// argument type is ::std::wstring.
-TEST(IsSubstringTest, ReturnsCorrectResultForStdWstring) {
- EXPECT_TRUE(IsSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
- EXPECT_FALSE(IsSubstring("", "", L"needle", ::std::wstring(L"haystack")));
-}
-
-// Tests that IsSubstring() generates the correct message when the input
-// argument type is ::std::wstring.
-TEST(IsSubstringTest, GeneratesCorrectMessageForWstring) {
- EXPECT_STREQ("Value of: needle_expr\n"
- " Actual: L\"needle\"\n"
- "Expected: a substring of haystack_expr\n"
- "Which is: L\"haystack\"",
- IsSubstring(
- "needle_expr", "haystack_expr",
- ::std::wstring(L"needle"), L"haystack").failure_message());
-}
-
-#endif // GTEST_HAS_STD_WSTRING
-
-// Tests for ::testing::IsNotSubstring().
-
-// Tests that IsNotSubstring() returns the correct result when the input
-// argument type is const char*.
-TEST(IsNotSubstringTest, ReturnsCorrectResultForCString) {
- EXPECT_TRUE(IsNotSubstring("", "", "needle", "haystack"));
- EXPECT_FALSE(IsNotSubstring("", "", "needle", "two needles"));
-}
-
-// Tests that IsNotSubstring() returns the correct result when the input
-// argument type is const wchar_t*.
-TEST(IsNotSubstringTest, ReturnsCorrectResultForWideCString) {
- EXPECT_TRUE(IsNotSubstring("", "", L"needle", L"haystack"));
- EXPECT_FALSE(IsNotSubstring("", "", L"needle", L"two needles"));
-}
-
-// Tests that IsNotSubstring() generates the correct message when the input
-// argument type is const wchar_t*.
-TEST(IsNotSubstringTest, GeneratesCorrectMessageForWideCString) {
- EXPECT_STREQ("Value of: needle_expr\n"
- " Actual: L\"needle\"\n"
- "Expected: not a substring of haystack_expr\n"
- "Which is: L\"two needles\"",
- IsNotSubstring(
- "needle_expr", "haystack_expr",
- L"needle", L"two needles").failure_message());
-}
-
-// Tests that IsNotSubstring returns the correct result when the input
-// argument type is ::std::string.
-TEST(IsNotSubstringTest, ReturnsCorrectResultsForStdString) {
- EXPECT_FALSE(IsNotSubstring("", "", std::string("hello"), "ahellob"));
- EXPECT_TRUE(IsNotSubstring("", "", "hello", std::string("world")));
-}
-
-// Tests that IsNotSubstring() generates the correct message when the input
-// argument type is ::std::string.
-TEST(IsNotSubstringTest, GeneratesCorrectMessageForStdString) {
- EXPECT_STREQ("Value of: needle_expr\n"
- " Actual: \"needle\"\n"
- "Expected: not a substring of haystack_expr\n"
- "Which is: \"two needles\"",
- IsNotSubstring(
- "needle_expr", "haystack_expr",
- ::std::string("needle"), "two needles").failure_message());
-}
-
-#if GTEST_HAS_STD_WSTRING
-
-// Tests that IsNotSubstring returns the correct result when the input
-// argument type is ::std::wstring.
-TEST(IsNotSubstringTest, ReturnsCorrectResultForStdWstring) {
- EXPECT_FALSE(
- IsNotSubstring("", "", ::std::wstring(L"needle"), L"two needles"));
- EXPECT_TRUE(IsNotSubstring("", "", L"needle", ::std::wstring(L"haystack")));
-}
-
-#endif // GTEST_HAS_STD_WSTRING
-
-// Tests floating-point assertions.
-
-template <typename RawType>
-class FloatingPointTest : public Test {
- protected:
- // Pre-calculated numbers to be used by the tests.
- struct TestValues {
- RawType close_to_positive_zero;
- RawType close_to_negative_zero;
- RawType further_from_negative_zero;
-
- RawType close_to_one;
- RawType further_from_one;
-
- RawType infinity;
- RawType close_to_infinity;
- RawType further_from_infinity;
-
- RawType nan1;
- RawType nan2;
- };
-
- typedef typename testing::internal::FloatingPoint<RawType> Floating;
- typedef typename Floating::Bits Bits;
-
- void SetUp() override {
- const size_t max_ulps = Floating::kMaxUlps;
-
- // The bits that represent 0.0.
- const Bits zero_bits = Floating(0).bits();
-
- // Makes some numbers close to 0.0.
- values_.close_to_positive_zero = Floating::ReinterpretBits(
- zero_bits + max_ulps/2);
- values_.close_to_negative_zero = -Floating::ReinterpretBits(
- zero_bits + max_ulps - max_ulps/2);
- values_.further_from_negative_zero = -Floating::ReinterpretBits(
- zero_bits + max_ulps + 1 - max_ulps/2);
-
- // The bits that represent 1.0.
- const Bits one_bits = Floating(1).bits();
-
- // Makes some numbers close to 1.0.
- values_.close_to_one = Floating::ReinterpretBits(one_bits + max_ulps);
- values_.further_from_one = Floating::ReinterpretBits(
- one_bits + max_ulps + 1);
-
- // +infinity.
- values_.infinity = Floating::Infinity();
-
- // The bits that represent +infinity.
- const Bits infinity_bits = Floating(values_.infinity).bits();
-
- // Makes some numbers close to infinity.
- values_.close_to_infinity = Floating::ReinterpretBits(
- infinity_bits - max_ulps);
- values_.further_from_infinity = Floating::ReinterpretBits(
- infinity_bits - max_ulps - 1);
-
- // Makes some NAN's. Sets the most significant bit of the fraction so that
- // our NaN's are quiet; trying to process a signaling NaN would raise an
- // exception if our environment enables floating point exceptions.
- values_.nan1 = Floating::ReinterpretBits(Floating::kExponentBitMask
- | (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 1);
- values_.nan2 = Floating::ReinterpretBits(Floating::kExponentBitMask
- | (static_cast<Bits>(1) << (Floating::kFractionBitCount - 1)) | 200);
- }
-
- void TestSize() {
- EXPECT_EQ(sizeof(RawType), sizeof(Bits));
- }
-
- static TestValues values_;
-};
-
-template <typename RawType>
-typename FloatingPointTest<RawType>::TestValues
- FloatingPointTest<RawType>::values_;
-
-// Instantiates FloatingPointTest for testing *_FLOAT_EQ.
-typedef FloatingPointTest<float> FloatTest;
-
-// Tests that the size of Float::Bits matches the size of float.
-TEST_F(FloatTest, Size) {
- TestSize();
-}
-
-// Tests comparing with +0 and -0.
-TEST_F(FloatTest, Zeros) {
- EXPECT_FLOAT_EQ(0.0, -0.0);
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(-0.0, 1.0),
- "1.0");
- EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.5),
- "1.5");
-}
-
-// Tests comparing numbers close to 0.
-//
-// This ensures that *_FLOAT_EQ handles the sign correctly and no
-// overflow occurs when comparing numbers whose absolute value is very
-// small.
-TEST_F(FloatTest, AlmostZeros) {
- // In C++Builder, names within local classes (such as used by
- // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
- // scoping class. Use a static local alias as a workaround.
- // We use the assignment syntax since some compilers, like Sun Studio,
- // don't allow initializing references using construction syntax
- // (parentheses).
- static const FloatTest::TestValues& v = this->values_;
-
- EXPECT_FLOAT_EQ(0.0, v.close_to_positive_zero);
- EXPECT_FLOAT_EQ(-0.0, v.close_to_negative_zero);
- EXPECT_FLOAT_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
-
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_FLOAT_EQ(v.close_to_positive_zero,
- v.further_from_negative_zero);
- }, "v.further_from_negative_zero");
-}
-
-// Tests comparing numbers close to each other.
-TEST_F(FloatTest, SmallDiff) {
- EXPECT_FLOAT_EQ(1.0, values_.close_to_one);
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, values_.further_from_one),
- "values_.further_from_one");
-}
-
-// Tests comparing numbers far apart.
-TEST_F(FloatTest, LargeDiff) {
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(2.5, 3.0),
- "3.0");
-}
-
-// Tests comparing with infinity.
-//
-// This ensures that no overflow occurs when comparing numbers whose
-// absolute value is very large.
-TEST_F(FloatTest, Infinity) {
- EXPECT_FLOAT_EQ(values_.infinity, values_.close_to_infinity);
- EXPECT_FLOAT_EQ(-values_.infinity, -values_.close_to_infinity);
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, -values_.infinity),
- "-values_.infinity");
-
- // This is interesting as the representations of infinity and nan1
- // are only 1 DLP apart.
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.infinity, values_.nan1),
- "values_.nan1");
-}
-
-// Tests that comparing with NAN always returns false.
-TEST_F(FloatTest, NaN) {
- // In C++Builder, names within local classes (such as used by
- // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
- // scoping class. Use a static local alias as a workaround.
- // We use the assignment syntax since some compilers, like Sun Studio,
- // don't allow initializing references using construction syntax
- // (parentheses).
- static const FloatTest::TestValues& v = this->values_;
-
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan1),
- "v.nan1");
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(v.nan1, v.nan2),
- "v.nan2");
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(1.0, v.nan1),
- "v.nan1");
-
- EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(v.nan1, v.infinity),
- "v.infinity");
-}
-
-// Tests that *_FLOAT_EQ are reflexive.
-TEST_F(FloatTest, Reflexive) {
- EXPECT_FLOAT_EQ(0.0, 0.0);
- EXPECT_FLOAT_EQ(1.0, 1.0);
- ASSERT_FLOAT_EQ(values_.infinity, values_.infinity);
-}
-
-// Tests that *_FLOAT_EQ are commutative.
-TEST_F(FloatTest, Commutative) {
- // We already tested EXPECT_FLOAT_EQ(1.0, values_.close_to_one).
- EXPECT_FLOAT_EQ(values_.close_to_one, 1.0);
-
- // We already tested EXPECT_FLOAT_EQ(1.0, values_.further_from_one).
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(values_.further_from_one, 1.0),
- "1.0");
-}
-
-// Tests EXPECT_NEAR.
-TEST_F(FloatTest, EXPECT_NEAR) {
- EXPECT_NEAR(-1.0f, -1.1f, 0.2f);
- EXPECT_NEAR(2.0f, 3.0f, 1.0f);
- EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0f,1.5f, 0.25f), // NOLINT
- "The difference between 1.0f and 1.5f is 0.5, "
- "which exceeds 0.25f");
- // To work around a bug in gcc 2.95.0, there is intentionally no
- // space after the first comma in the previous line.
-}
-
-// Tests ASSERT_NEAR.
-TEST_F(FloatTest, ASSERT_NEAR) {
- ASSERT_NEAR(-1.0f, -1.1f, 0.2f);
- ASSERT_NEAR(2.0f, 3.0f, 1.0f);
- EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0f,1.5f, 0.25f), // NOLINT
- "The difference between 1.0f and 1.5f is 0.5, "
- "which exceeds 0.25f");
- // To work around a bug in gcc 2.95.0, there is intentionally no
- // space after the first comma in the previous line.
-}
-
-// Tests the cases where FloatLE() should succeed.
-TEST_F(FloatTest, FloatLESucceeds) {
- EXPECT_PRED_FORMAT2(FloatLE, 1.0f, 2.0f); // When val1 < val2,
- ASSERT_PRED_FORMAT2(FloatLE, 1.0f, 1.0f); // val1 == val2,
-
- // or when val1 is greater than, but almost equals to, val2.
- EXPECT_PRED_FORMAT2(FloatLE, values_.close_to_positive_zero, 0.0f);
-}
-
-// Tests the cases where FloatLE() should fail.
-TEST_F(FloatTest, FloatLEFails) {
- // When val1 is greater than val2 by a large margin,
- EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(FloatLE, 2.0f, 1.0f),
- "(2.0f) <= (1.0f)");
-
- // or by a small yet non-negligible margin,
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(FloatLE, values_.further_from_one, 1.0f);
- }, "(values_.further_from_one) <= (1.0f)");
-
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(FloatLE, values_.nan1, values_.infinity);
- }, "(values_.nan1) <= (values_.infinity)");
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(FloatLE, -values_.infinity, values_.nan1);
- }, "(-values_.infinity) <= (values_.nan1)");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT2(FloatLE, values_.nan1, values_.nan1);
- }, "(values_.nan1) <= (values_.nan1)");
-}
-
-// Instantiates FloatingPointTest for testing *_DOUBLE_EQ.
-typedef FloatingPointTest<double> DoubleTest;
-
-// Tests that the size of Double::Bits matches the size of double.
-TEST_F(DoubleTest, Size) {
- TestSize();
-}
-
-// Tests comparing with +0 and -0.
-TEST_F(DoubleTest, Zeros) {
- EXPECT_DOUBLE_EQ(0.0, -0.0);
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(-0.0, 1.0),
- "1.0");
- EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(0.0, 1.0),
- "1.0");
-}
-
-// Tests comparing numbers close to 0.
-//
-// This ensures that *_DOUBLE_EQ handles the sign correctly and no
-// overflow occurs when comparing numbers whose absolute value is very
-// small.
-TEST_F(DoubleTest, AlmostZeros) {
- // In C++Builder, names within local classes (such as used by
- // EXPECT_FATAL_FAILURE) cannot be resolved against static members of the
- // scoping class. Use a static local alias as a workaround.
- // We use the assignment syntax since some compilers, like Sun Studio,
- // don't allow initializing references using construction syntax
- // (parentheses).
- static const DoubleTest::TestValues& v = this->values_;
-
- EXPECT_DOUBLE_EQ(0.0, v.close_to_positive_zero);
- EXPECT_DOUBLE_EQ(-0.0, v.close_to_negative_zero);
- EXPECT_DOUBLE_EQ(v.close_to_positive_zero, v.close_to_negative_zero);
-
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_DOUBLE_EQ(v.close_to_positive_zero,
- v.further_from_negative_zero);
- }, "v.further_from_negative_zero");
-}
-
-// Tests comparing numbers close to each other.
-TEST_F(DoubleTest, SmallDiff) {
- EXPECT_DOUBLE_EQ(1.0, values_.close_to_one);
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, values_.further_from_one),
- "values_.further_from_one");
-}
-
-// Tests comparing numbers far apart.
-TEST_F(DoubleTest, LargeDiff) {
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(2.0, 3.0),
- "3.0");
-}
-
-// Tests comparing with infinity.
-//
-// This ensures that no overflow occurs when comparing numbers whose
-// absolute value is very large.
-TEST_F(DoubleTest, Infinity) {
- EXPECT_DOUBLE_EQ(values_.infinity, values_.close_to_infinity);
- EXPECT_DOUBLE_EQ(-values_.infinity, -values_.close_to_infinity);
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, -values_.infinity),
- "-values_.infinity");
-
- // This is interesting as the representations of infinity_ and nan1_
- // are only 1 DLP apart.
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.infinity, values_.nan1),
- "values_.nan1");
-}
-
-// Tests that comparing with NAN always returns false.
-TEST_F(DoubleTest, NaN) {
- static const DoubleTest::TestValues& v = this->values_;
-
- // Nokia's STLport crashes if we try to output infinity or NaN.
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan1),
- "v.nan1");
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(v.nan1, v.nan2), "v.nan2");
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1.0, v.nan1), "v.nan1");
- EXPECT_FATAL_FAILURE(ASSERT_DOUBLE_EQ(v.nan1, v.infinity),
- "v.infinity");
-}
-
-// Tests that *_DOUBLE_EQ are reflexive.
-TEST_F(DoubleTest, Reflexive) {
- EXPECT_DOUBLE_EQ(0.0, 0.0);
- EXPECT_DOUBLE_EQ(1.0, 1.0);
- ASSERT_DOUBLE_EQ(values_.infinity, values_.infinity);
-}
-
-// Tests that *_DOUBLE_EQ are commutative.
-TEST_F(DoubleTest, Commutative) {
- // We already tested EXPECT_DOUBLE_EQ(1.0, values_.close_to_one).
- EXPECT_DOUBLE_EQ(values_.close_to_one, 1.0);
-
- // We already tested EXPECT_DOUBLE_EQ(1.0, values_.further_from_one).
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(values_.further_from_one, 1.0),
- "1.0");
-}
-
-// Tests EXPECT_NEAR.
-TEST_F(DoubleTest, EXPECT_NEAR) {
- EXPECT_NEAR(-1.0, -1.1, 0.2);
- EXPECT_NEAR(2.0, 3.0, 1.0);
- EXPECT_NONFATAL_FAILURE(EXPECT_NEAR(1.0, 1.5, 0.25), // NOLINT
- "The difference between 1.0 and 1.5 is 0.5, "
- "which exceeds 0.25");
- // To work around a bug in gcc 2.95.0, there is intentionally no
- // space after the first comma in the previous statement.
-}
-
-// Tests ASSERT_NEAR.
-TEST_F(DoubleTest, ASSERT_NEAR) {
- ASSERT_NEAR(-1.0, -1.1, 0.2);
- ASSERT_NEAR(2.0, 3.0, 1.0);
- EXPECT_FATAL_FAILURE(ASSERT_NEAR(1.0, 1.5, 0.25), // NOLINT
- "The difference between 1.0 and 1.5 is 0.5, "
- "which exceeds 0.25");
- // To work around a bug in gcc 2.95.0, there is intentionally no
- // space after the first comma in the previous statement.
-}
-
-// Tests the cases where DoubleLE() should succeed.
-TEST_F(DoubleTest, DoubleLESucceeds) {
- EXPECT_PRED_FORMAT2(DoubleLE, 1.0, 2.0); // When val1 < val2,
- ASSERT_PRED_FORMAT2(DoubleLE, 1.0, 1.0); // val1 == val2,
-
- // or when val1 is greater than, but almost equals to, val2.
- EXPECT_PRED_FORMAT2(DoubleLE, values_.close_to_positive_zero, 0.0);
-}
-
-// Tests the cases where DoubleLE() should fail.
-TEST_F(DoubleTest, DoubleLEFails) {
- // When val1 is greater than val2 by a large margin,
- EXPECT_NONFATAL_FAILURE(EXPECT_PRED_FORMAT2(DoubleLE, 2.0, 1.0),
- "(2.0) <= (1.0)");
-
- // or by a small yet non-negligible margin,
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(DoubleLE, values_.further_from_one, 1.0);
- }, "(values_.further_from_one) <= (1.0)");
-
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.infinity);
- }, "(values_.nan1) <= (values_.infinity)");
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_PRED_FORMAT2(DoubleLE, -values_.infinity, values_.nan1);
- }, " (-values_.infinity) <= (values_.nan1)");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_PRED_FORMAT2(DoubleLE, values_.nan1, values_.nan1);
- }, "(values_.nan1) <= (values_.nan1)");
-}
-
-
-// Verifies that a test or test case whose name starts with DISABLED_ is
-// not run.
-
-// A test whose name starts with DISABLED_.
-// Should not run.
-TEST(DisabledTest, DISABLED_TestShouldNotRun) {
- FAIL() << "Unexpected failure: Disabled test should not be run.";
-}
-
-// A test whose name does not start with DISABLED_.
-// Should run.
-TEST(DisabledTest, NotDISABLED_TestShouldRun) {
- EXPECT_EQ(1, 1);
-}
-
-// A test case whose name starts with DISABLED_.
-// Should not run.
-TEST(DISABLED_TestSuite, TestShouldNotRun) {
- FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
-}
-
-// A test case and test whose names start with DISABLED_.
-// Should not run.
-TEST(DISABLED_TestSuite, DISABLED_TestShouldNotRun) {
- FAIL() << "Unexpected failure: Test in disabled test case should not be run.";
-}
-
-// Check that when all tests in a test case are disabled, SetUpTestSuite() and
-// TearDownTestSuite() are not called.
-class DisabledTestsTest : public Test {
- protected:
- static void SetUpTestSuite() {
- FAIL() << "Unexpected failure: All tests disabled in test case. "
- "SetUpTestSuite() should not be called.";
- }
-
- static void TearDownTestSuite() {
- FAIL() << "Unexpected failure: All tests disabled in test case. "
- "TearDownTestSuite() should not be called.";
- }
-};
-
-TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_1) {
- FAIL() << "Unexpected failure: Disabled test should not be run.";
-}
-
-TEST_F(DisabledTestsTest, DISABLED_TestShouldNotRun_2) {
- FAIL() << "Unexpected failure: Disabled test should not be run.";
-}
-
-// Tests that disabled typed tests aren't run.
-
-#if GTEST_HAS_TYPED_TEST
-
-template <typename T>
-class TypedTest : public Test {
-};
-
-typedef testing::Types<int, double> NumericTypes;
-TYPED_TEST_SUITE(TypedTest, NumericTypes);
-
-TYPED_TEST(TypedTest, DISABLED_ShouldNotRun) {
- FAIL() << "Unexpected failure: Disabled typed test should not run.";
-}
-
-template <typename T>
-class DISABLED_TypedTest : public Test {
-};
-
-TYPED_TEST_SUITE(DISABLED_TypedTest, NumericTypes);
-
-TYPED_TEST(DISABLED_TypedTest, ShouldNotRun) {
- FAIL() << "Unexpected failure: Disabled typed test should not run.";
-}
-
-#endif // GTEST_HAS_TYPED_TEST
-
-// Tests that disabled type-parameterized tests aren't run.
-
-#if GTEST_HAS_TYPED_TEST_P
-
-template <typename T>
-class TypedTestP : public Test {
-};
-
-TYPED_TEST_SUITE_P(TypedTestP);
-
-TYPED_TEST_P(TypedTestP, DISABLED_ShouldNotRun) {
- FAIL() << "Unexpected failure: "
- << "Disabled type-parameterized test should not run.";
-}
-
-REGISTER_TYPED_TEST_SUITE_P(TypedTestP, DISABLED_ShouldNotRun);
-
-INSTANTIATE_TYPED_TEST_SUITE_P(My, TypedTestP, NumericTypes);
-
-template <typename T>
-class DISABLED_TypedTestP : public Test {
-};
-
-TYPED_TEST_SUITE_P(DISABLED_TypedTestP);
-
-TYPED_TEST_P(DISABLED_TypedTestP, ShouldNotRun) {
- FAIL() << "Unexpected failure: "
- << "Disabled type-parameterized test should not run.";
-}
-
-REGISTER_TYPED_TEST_SUITE_P(DISABLED_TypedTestP, ShouldNotRun);
-
-INSTANTIATE_TYPED_TEST_SUITE_P(My, DISABLED_TypedTestP, NumericTypes);
-
-#endif // GTEST_HAS_TYPED_TEST_P
-
-// Tests that assertion macros evaluate their arguments exactly once.
-
-class SingleEvaluationTest : public Test {
- public: // Must be public and not protected due to a bug in g++ 3.4.2.
- // This helper function is needed by the FailedASSERT_STREQ test
- // below. It's public to work around C++Builder's bug with scoping local
- // classes.
- static void CompareAndIncrementCharPtrs() {
- ASSERT_STREQ(p1_++, p2_++);
- }
-
- // This helper function is needed by the FailedASSERT_NE test below. It's
- // public to work around C++Builder's bug with scoping local classes.
- static void CompareAndIncrementInts() {
- ASSERT_NE(a_++, b_++);
- }
-
- protected:
- SingleEvaluationTest() {
- p1_ = s1_;
- p2_ = s2_;
- a_ = 0;
- b_ = 0;
- }
-
- static const char* const s1_;
- static const char* const s2_;
- static const char* p1_;
- static const char* p2_;
-
- static int a_;
- static int b_;
-};
-
-const char* const SingleEvaluationTest::s1_ = "01234";
-const char* const SingleEvaluationTest::s2_ = "abcde";
-const char* SingleEvaluationTest::p1_;
-const char* SingleEvaluationTest::p2_;
-int SingleEvaluationTest::a_;
-int SingleEvaluationTest::b_;
-
-// Tests that when ASSERT_STREQ fails, it evaluates its arguments
-// exactly once.
-TEST_F(SingleEvaluationTest, FailedASSERT_STREQ) {
- EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementCharPtrs(),
- "p2_++");
- EXPECT_EQ(s1_ + 1, p1_);
- EXPECT_EQ(s2_ + 1, p2_);
-}
-
-// Tests that string assertion arguments are evaluated exactly once.
-TEST_F(SingleEvaluationTest, ASSERT_STR) {
- // successful EXPECT_STRNE
- EXPECT_STRNE(p1_++, p2_++);
- EXPECT_EQ(s1_ + 1, p1_);
- EXPECT_EQ(s2_ + 1, p2_);
-
- // failed EXPECT_STRCASEEQ
- EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ(p1_++, p2_++),
- "Ignoring case");
- EXPECT_EQ(s1_ + 2, p1_);
- EXPECT_EQ(s2_ + 2, p2_);
-}
-
-// Tests that when ASSERT_NE fails, it evaluates its arguments exactly
-// once.
-TEST_F(SingleEvaluationTest, FailedASSERT_NE) {
- EXPECT_FATAL_FAILURE(SingleEvaluationTest::CompareAndIncrementInts(),
- "(a_++) != (b_++)");
- EXPECT_EQ(1, a_);
- EXPECT_EQ(1, b_);
-}
-
-// Tests that assertion arguments are evaluated exactly once.
-TEST_F(SingleEvaluationTest, OtherCases) {
- // successful EXPECT_TRUE
- EXPECT_TRUE(0 == a_++); // NOLINT
- EXPECT_EQ(1, a_);
-
- // failed EXPECT_TRUE
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(-1 == a_++), "-1 == a_++");
- EXPECT_EQ(2, a_);
-
- // successful EXPECT_GT
- EXPECT_GT(a_++, b_++);
- EXPECT_EQ(3, a_);
- EXPECT_EQ(1, b_);
-
- // failed EXPECT_LT
- EXPECT_NONFATAL_FAILURE(EXPECT_LT(a_++, b_++), "(a_++) < (b_++)");
- EXPECT_EQ(4, a_);
- EXPECT_EQ(2, b_);
-
- // successful ASSERT_TRUE
- ASSERT_TRUE(0 < a_++); // NOLINT
- EXPECT_EQ(5, a_);
-
- // successful ASSERT_GT
- ASSERT_GT(a_++, b_++);
- EXPECT_EQ(6, a_);
- EXPECT_EQ(3, b_);
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-void ThrowAnInteger() {
- throw 1;
-}
-
-// Tests that assertion arguments are evaluated exactly once.
-TEST_F(SingleEvaluationTest, ExceptionTests) {
- // successful EXPECT_THROW
- EXPECT_THROW({ // NOLINT
- a_++;
- ThrowAnInteger();
- }, int);
- EXPECT_EQ(1, a_);
-
- // failed EXPECT_THROW, throws different
- EXPECT_NONFATAL_FAILURE(EXPECT_THROW({ // NOLINT
- a_++;
- ThrowAnInteger();
- }, bool), "throws a different type");
- EXPECT_EQ(2, a_);
-
- // failed EXPECT_THROW, throws nothing
- EXPECT_NONFATAL_FAILURE(EXPECT_THROW(a_++, bool), "throws nothing");
- EXPECT_EQ(3, a_);
-
- // successful EXPECT_NO_THROW
- EXPECT_NO_THROW(a_++);
- EXPECT_EQ(4, a_);
-
- // failed EXPECT_NO_THROW
- EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW({ // NOLINT
- a_++;
- ThrowAnInteger();
- }), "it throws");
- EXPECT_EQ(5, a_);
-
- // successful EXPECT_ANY_THROW
- EXPECT_ANY_THROW({ // NOLINT
- a_++;
- ThrowAnInteger();
- });
- EXPECT_EQ(6, a_);
-
- // failed EXPECT_ANY_THROW
- EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(a_++), "it doesn't");
- EXPECT_EQ(7, a_);
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// Tests {ASSERT|EXPECT}_NO_FATAL_FAILURE.
-class NoFatalFailureTest : public Test {
- protected:
- void Succeeds() {}
- void FailsNonFatal() {
- ADD_FAILURE() << "some non-fatal failure";
- }
- void Fails() {
- FAIL() << "some fatal failure";
- }
-
- void DoAssertNoFatalFailureOnFails() {
- ASSERT_NO_FATAL_FAILURE(Fails());
- ADD_FAILURE() << "should not reach here.";
- }
-
- void DoExpectNoFatalFailureOnFails() {
- EXPECT_NO_FATAL_FAILURE(Fails());
- ADD_FAILURE() << "other failure";
- }
-};
-
-TEST_F(NoFatalFailureTest, NoFailure) {
- EXPECT_NO_FATAL_FAILURE(Succeeds());
- ASSERT_NO_FATAL_FAILURE(Succeeds());
-}
-
-TEST_F(NoFatalFailureTest, NonFatalIsNoFailure) {
- EXPECT_NONFATAL_FAILURE(
- EXPECT_NO_FATAL_FAILURE(FailsNonFatal()),
- "some non-fatal failure");
- EXPECT_NONFATAL_FAILURE(
- ASSERT_NO_FATAL_FAILURE(FailsNonFatal()),
- "some non-fatal failure");
-}
-
-TEST_F(NoFatalFailureTest, AssertNoFatalFailureOnFatalFailure) {
- TestPartResultArray gtest_failures;
- {
- ScopedFakeTestPartResultReporter gtest_reporter(>est_failures);
- DoAssertNoFatalFailureOnFails();
- }
- ASSERT_EQ(2, gtest_failures.size());
- EXPECT_EQ(TestPartResult::kFatalFailure,
- gtest_failures.GetTestPartResult(0).type());
- EXPECT_EQ(TestPartResult::kFatalFailure,
- gtest_failures.GetTestPartResult(1).type());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
- gtest_failures.GetTestPartResult(0).message());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
- gtest_failures.GetTestPartResult(1).message());
-}
-
-TEST_F(NoFatalFailureTest, ExpectNoFatalFailureOnFatalFailure) {
- TestPartResultArray gtest_failures;
- {
- ScopedFakeTestPartResultReporter gtest_reporter(>est_failures);
- DoExpectNoFatalFailureOnFails();
- }
- ASSERT_EQ(3, gtest_failures.size());
- EXPECT_EQ(TestPartResult::kFatalFailure,
- gtest_failures.GetTestPartResult(0).type());
- EXPECT_EQ(TestPartResult::kNonFatalFailure,
- gtest_failures.GetTestPartResult(1).type());
- EXPECT_EQ(TestPartResult::kNonFatalFailure,
- gtest_failures.GetTestPartResult(2).type());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "some fatal failure",
- gtest_failures.GetTestPartResult(0).message());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "it does",
- gtest_failures.GetTestPartResult(1).message());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "other failure",
- gtest_failures.GetTestPartResult(2).message());
-}
-
-TEST_F(NoFatalFailureTest, MessageIsStreamable) {
- TestPartResultArray gtest_failures;
- {
- ScopedFakeTestPartResultReporter gtest_reporter(>est_failures);
- EXPECT_NO_FATAL_FAILURE(FAIL() << "foo") << "my message";
- }
- ASSERT_EQ(2, gtest_failures.size());
- EXPECT_EQ(TestPartResult::kNonFatalFailure,
- gtest_failures.GetTestPartResult(0).type());
- EXPECT_EQ(TestPartResult::kNonFatalFailure,
- gtest_failures.GetTestPartResult(1).type());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "foo",
- gtest_failures.GetTestPartResult(0).message());
- EXPECT_PRED_FORMAT2(testing::IsSubstring, "my message",
- gtest_failures.GetTestPartResult(1).message());
-}
-
-// Tests non-string assertions.
-
-std::string EditsToString(const std::vector<EditType>& edits) {
- std::string out;
- for (size_t i = 0; i < edits.size(); ++i) {
- static const char kEdits[] = " +-/";
- out.append(1, kEdits[edits[i]]);
- }
- return out;
-}
-
-std::vector<size_t> CharsToIndices(const std::string& str) {
- std::vector<size_t> out;
- for (size_t i = 0; i < str.size(); ++i) {
- out.push_back(static_cast<size_t>(str[i]));
- }
- return out;
-}
-
-std::vector<std::string> CharsToLines(const std::string& str) {
- std::vector<std::string> out;
- for (size_t i = 0; i < str.size(); ++i) {
- out.push_back(str.substr(i, 1));
- }
- return out;
-}
-
-TEST(EditDistance, TestSuites) {
- struct Case {
- int line;
- const char* left;
- const char* right;
- const char* expected_edits;
- const char* expected_diff;
- };
- static const Case kCases[] = {
- // No change.
- {__LINE__, "A", "A", " ", ""},
- {__LINE__, "ABCDE", "ABCDE", " ", ""},
- // Simple adds.
- {__LINE__, "X", "XA", " +", "@@ +1,2 @@\n X\n+A\n"},
- {__LINE__, "X", "XABCD", " ++++", "@@ +1,5 @@\n X\n+A\n+B\n+C\n+D\n"},
- // Simple removes.
- {__LINE__, "XA", "X", " -", "@@ -1,2 @@\n X\n-A\n"},
- {__LINE__, "XABCD", "X", " ----", "@@ -1,5 @@\n X\n-A\n-B\n-C\n-D\n"},
- // Simple replaces.
- {__LINE__, "A", "a", "/", "@@ -1,1 +1,1 @@\n-A\n+a\n"},
- {__LINE__, "ABCD", "abcd", "////",
- "@@ -1,4 +1,4 @@\n-A\n-B\n-C\n-D\n+a\n+b\n+c\n+d\n"},
- // Path finding.
- {__LINE__, "ABCDEFGH", "ABXEGH1", " -/ - +",
- "@@ -1,8 +1,7 @@\n A\n B\n-C\n-D\n+X\n E\n-F\n G\n H\n+1\n"},
- {__LINE__, "AAAABCCCC", "ABABCDCDC", "- / + / ",
- "@@ -1,9 +1,9 @@\n-A\n A\n-A\n+B\n A\n B\n C\n+D\n C\n-C\n+D\n C\n"},
- {__LINE__, "ABCDE", "BCDCD", "- +/",
- "@@ -1,5 +1,5 @@\n-A\n B\n C\n D\n-E\n+C\n+D\n"},
- {__LINE__, "ABCDEFGHIJKL", "BCDCDEFGJKLJK", "- ++ -- ++",
- "@@ -1,4 +1,5 @@\n-A\n B\n+C\n+D\n C\n D\n"
- "@@ -6,7 +7,7 @@\n F\n G\n-H\n-I\n J\n K\n L\n+J\n+K\n"},
- {}};
- for (const Case* c = kCases; c->left; ++c) {
- EXPECT_TRUE(c->expected_edits ==
- EditsToString(CalculateOptimalEdits(CharsToIndices(c->left),
- CharsToIndices(c->right))))
- << "Left <" << c->left << "> Right <" << c->right << "> Edits <"
- << EditsToString(CalculateOptimalEdits(
- CharsToIndices(c->left), CharsToIndices(c->right))) << ">";
- EXPECT_TRUE(c->expected_diff == CreateUnifiedDiff(CharsToLines(c->left),
- CharsToLines(c->right)))
- << "Left <" << c->left << "> Right <" << c->right << "> Diff <"
- << CreateUnifiedDiff(CharsToLines(c->left), CharsToLines(c->right))
- << ">";
- }
-}
-
-// Tests EqFailure(), used for implementing *EQ* assertions.
-TEST(AssertionTest, EqFailure) {
- const std::string foo_val("5"), bar_val("6");
- const std::string msg1(
- EqFailure("foo", "bar", foo_val, bar_val, false)
- .failure_message());
- EXPECT_STREQ(
- "Expected equality of these values:\n"
- " foo\n"
- " Which is: 5\n"
- " bar\n"
- " Which is: 6",
- msg1.c_str());
-
- const std::string msg2(
- EqFailure("foo", "6", foo_val, bar_val, false)
- .failure_message());
- EXPECT_STREQ(
- "Expected equality of these values:\n"
- " foo\n"
- " Which is: 5\n"
- " 6",
- msg2.c_str());
-
- const std::string msg3(
- EqFailure("5", "bar", foo_val, bar_val, false)
- .failure_message());
- EXPECT_STREQ(
- "Expected equality of these values:\n"
- " 5\n"
- " bar\n"
- " Which is: 6",
- msg3.c_str());
-
- const std::string msg4(
- EqFailure("5", "6", foo_val, bar_val, false).failure_message());
- EXPECT_STREQ(
- "Expected equality of these values:\n"
- " 5\n"
- " 6",
- msg4.c_str());
-
- const std::string msg5(
- EqFailure("foo", "bar",
- std::string("\"x\""), std::string("\"y\""),
- true).failure_message());
- EXPECT_STREQ(
- "Expected equality of these values:\n"
- " foo\n"
- " Which is: \"x\"\n"
- " bar\n"
- " Which is: \"y\"\n"
- "Ignoring case",
- msg5.c_str());
-}
-
-TEST(AssertionTest, EqFailureWithDiff) {
- const std::string left(
- "1\\n2XXX\\n3\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12XXX\\n13\\n14\\n15");
- const std::string right(
- "1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n11\\n12\\n13\\n14");
- const std::string msg1(
- EqFailure("left", "right", left, right, false).failure_message());
- EXPECT_STREQ(
- "Expected equality of these values:\n"
- " left\n"
- " Which is: "
- "1\\n2XXX\\n3\\n5\\n6\\n7\\n8\\n9\\n10\\n11\\n12XXX\\n13\\n14\\n15\n"
- " right\n"
- " Which is: 1\\n2\\n3\\n4\\n5\\n6\\n7\\n8\\n9\\n11\\n12\\n13\\n14\n"
- "With diff:\n@@ -1,5 +1,6 @@\n 1\n-2XXX\n+2\n 3\n+4\n 5\n 6\n"
- "@@ -7,8 +8,6 @@\n 8\n 9\n-10\n 11\n-12XXX\n+12\n 13\n 14\n-15\n",
- msg1.c_str());
-}
-
-// Tests AppendUserMessage(), used for implementing the *EQ* macros.
-TEST(AssertionTest, AppendUserMessage) {
- const std::string foo("foo");
-
- Message msg;
- EXPECT_STREQ("foo",
- AppendUserMessage(foo, msg).c_str());
-
- msg << "bar";
- EXPECT_STREQ("foo\nbar",
- AppendUserMessage(foo, msg).c_str());
-}
-
-#ifdef __BORLANDC__
-// Silences warnings: "Condition is always true", "Unreachable code"
-# pragma option push -w-ccc -w-rch
-#endif
-
-// Tests ASSERT_TRUE.
-TEST(AssertionTest, ASSERT_TRUE) {
- ASSERT_TRUE(2 > 1); // NOLINT
- EXPECT_FATAL_FAILURE(ASSERT_TRUE(2 < 1),
- "2 < 1");
-}
-
-// Tests ASSERT_TRUE(predicate) for predicates returning AssertionResult.
-TEST(AssertionTest, AssertTrueWithAssertionResult) {
- ASSERT_TRUE(ResultIsEven(2));
-#ifndef __BORLANDC__
- // ICE's in C++Builder.
- EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEven(3)),
- "Value of: ResultIsEven(3)\n"
- " Actual: false (3 is odd)\n"
- "Expected: true");
-#endif
- ASSERT_TRUE(ResultIsEvenNoExplanation(2));
- EXPECT_FATAL_FAILURE(ASSERT_TRUE(ResultIsEvenNoExplanation(3)),
- "Value of: ResultIsEvenNoExplanation(3)\n"
- " Actual: false (3 is odd)\n"
- "Expected: true");
-}
-
-// Tests ASSERT_FALSE.
-TEST(AssertionTest, ASSERT_FALSE) {
- ASSERT_FALSE(2 < 1); // NOLINT
- EXPECT_FATAL_FAILURE(ASSERT_FALSE(2 > 1),
- "Value of: 2 > 1\n"
- " Actual: true\n"
- "Expected: false");
-}
-
-// Tests ASSERT_FALSE(predicate) for predicates returning AssertionResult.
-TEST(AssertionTest, AssertFalseWithAssertionResult) {
- ASSERT_FALSE(ResultIsEven(3));
-#ifndef __BORLANDC__
- // ICE's in C++Builder.
- EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEven(2)),
- "Value of: ResultIsEven(2)\n"
- " Actual: true (2 is even)\n"
- "Expected: false");
-#endif
- ASSERT_FALSE(ResultIsEvenNoExplanation(3));
- EXPECT_FATAL_FAILURE(ASSERT_FALSE(ResultIsEvenNoExplanation(2)),
- "Value of: ResultIsEvenNoExplanation(2)\n"
- " Actual: true\n"
- "Expected: false");
-}
-
-#ifdef __BORLANDC__
-// Restores warnings after previous "#pragma option push" suppressed them
-# pragma option pop
-#endif
-
-// Tests using ASSERT_EQ on double values. The purpose is to make
-// sure that the specialization we did for integer and anonymous enums
-// isn't used for double arguments.
-TEST(ExpectTest, ASSERT_EQ_Double) {
- // A success.
- ASSERT_EQ(5.6, 5.6);
-
- // A failure.
- EXPECT_FATAL_FAILURE(ASSERT_EQ(5.1, 5.2),
- "5.1");
-}
-
-// Tests ASSERT_EQ.
-TEST(AssertionTest, ASSERT_EQ) {
- ASSERT_EQ(5, 2 + 3);
- EXPECT_FATAL_FAILURE(ASSERT_EQ(5, 2*3),
- "Expected equality of these values:\n"
- " 5\n"
- " 2*3\n"
- " Which is: 6");
-}
-
-// Tests ASSERT_EQ(NULL, pointer).
-TEST(AssertionTest, ASSERT_EQ_NULL) {
- // A success.
- const char* p = nullptr;
- // Some older GCC versions may issue a spurious warning in this or the next
- // assertion statement. This warning should not be suppressed with
- // static_cast since the test verifies the ability to use bare NULL as the
- // expected parameter to the macro.
- ASSERT_EQ(nullptr, p);
-
- // A failure.
- static int n = 0;
- EXPECT_FATAL_FAILURE(ASSERT_EQ(nullptr, &n), " &n\n Which is:");
-}
-
-// Tests ASSERT_EQ(0, non_pointer). Since the literal 0 can be
-// treated as a null pointer by the compiler, we need to make sure
-// that ASSERT_EQ(0, non_pointer) isn't interpreted by Google Test as
-// ASSERT_EQ(static_cast<void*>(NULL), non_pointer).
-TEST(ExpectTest, ASSERT_EQ_0) {
- int n = 0;
-
- // A success.
- ASSERT_EQ(0, n);
-
- // A failure.
- EXPECT_FATAL_FAILURE(ASSERT_EQ(0, 5.6),
- " 0\n 5.6");
-}
-
-// Tests ASSERT_NE.
-TEST(AssertionTest, ASSERT_NE) {
- ASSERT_NE(6, 7);
- EXPECT_FATAL_FAILURE(ASSERT_NE('a', 'a'),
- "Expected: ('a') != ('a'), "
- "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
-}
-
-// Tests ASSERT_LE.
-TEST(AssertionTest, ASSERT_LE) {
- ASSERT_LE(2, 3);
- ASSERT_LE(2, 2);
- EXPECT_FATAL_FAILURE(ASSERT_LE(2, 0),
- "Expected: (2) <= (0), actual: 2 vs 0");
-}
-
-// Tests ASSERT_LT.
-TEST(AssertionTest, ASSERT_LT) {
- ASSERT_LT(2, 3);
- EXPECT_FATAL_FAILURE(ASSERT_LT(2, 2),
- "Expected: (2) < (2), actual: 2 vs 2");
-}
-
-// Tests ASSERT_GE.
-TEST(AssertionTest, ASSERT_GE) {
- ASSERT_GE(2, 1);
- ASSERT_GE(2, 2);
- EXPECT_FATAL_FAILURE(ASSERT_GE(2, 3),
- "Expected: (2) >= (3), actual: 2 vs 3");
-}
-
-// Tests ASSERT_GT.
-TEST(AssertionTest, ASSERT_GT) {
- ASSERT_GT(2, 1);
- EXPECT_FATAL_FAILURE(ASSERT_GT(2, 2),
- "Expected: (2) > (2), actual: 2 vs 2");
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-void ThrowNothing() {}
-
-// Tests ASSERT_THROW.
-TEST(AssertionTest, ASSERT_THROW) {
- ASSERT_THROW(ThrowAnInteger(), int);
-
-# ifndef __BORLANDC__
-
- // ICE's in C++Builder 2007 and 2009.
- EXPECT_FATAL_FAILURE(
- ASSERT_THROW(ThrowAnInteger(), bool),
- "Expected: ThrowAnInteger() throws an exception of type bool.\n"
- " Actual: it throws a different type.");
-# endif
-
- EXPECT_FATAL_FAILURE(
- ASSERT_THROW(ThrowNothing(), bool),
- "Expected: ThrowNothing() throws an exception of type bool.\n"
- " Actual: it throws nothing.");
-}
-
-// Tests ASSERT_NO_THROW.
-TEST(AssertionTest, ASSERT_NO_THROW) {
- ASSERT_NO_THROW(ThrowNothing());
- EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()),
- "Expected: ThrowAnInteger() doesn't throw an exception."
- "\n Actual: it throws.");
-}
-
-// Tests ASSERT_ANY_THROW.
-TEST(AssertionTest, ASSERT_ANY_THROW) {
- ASSERT_ANY_THROW(ThrowAnInteger());
- EXPECT_FATAL_FAILURE(
- ASSERT_ANY_THROW(ThrowNothing()),
- "Expected: ThrowNothing() throws an exception.\n"
- " Actual: it doesn't.");
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// Makes sure we deal with the precedence of <<. This test should
-// compile.
-TEST(AssertionTest, AssertPrecedence) {
- ASSERT_EQ(1 < 2, true);
- bool false_value = false;
- ASSERT_EQ(true && false_value, false);
-}
-
-// A subroutine used by the following test.
-void TestEq1(int x) {
- ASSERT_EQ(1, x);
-}
-
-// Tests calling a test subroutine that's not part of a fixture.
-TEST(AssertionTest, NonFixtureSubroutine) {
- EXPECT_FATAL_FAILURE(TestEq1(2),
- " x\n Which is: 2");
-}
-
-// An uncopyable class.
-class Uncopyable {
- public:
- explicit Uncopyable(int a_value) : value_(a_value) {}
-
- int value() const { return value_; }
- bool operator==(const Uncopyable& rhs) const {
- return value() == rhs.value();
- }
- private:
- // This constructor deliberately has no implementation, as we don't
- // want this class to be copyable.
- Uncopyable(const Uncopyable&); // NOLINT
-
- int value_;
-};
-
-::std::ostream& operator<<(::std::ostream& os, const Uncopyable& value) {
- return os << value.value();
-}
-
-
-bool IsPositiveUncopyable(const Uncopyable& x) {
- return x.value() > 0;
-}
-
-// A subroutine used by the following test.
-void TestAssertNonPositive() {
- Uncopyable y(-1);
- ASSERT_PRED1(IsPositiveUncopyable, y);
-}
-// A subroutine used by the following test.
-void TestAssertEqualsUncopyable() {
- Uncopyable x(5);
- Uncopyable y(-1);
- ASSERT_EQ(x, y);
-}
-
-// Tests that uncopyable objects can be used in assertions.
-TEST(AssertionTest, AssertWorksWithUncopyableObject) {
- Uncopyable x(5);
- ASSERT_PRED1(IsPositiveUncopyable, x);
- ASSERT_EQ(x, x);
- EXPECT_FATAL_FAILURE(TestAssertNonPositive(),
- "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
- EXPECT_FATAL_FAILURE(TestAssertEqualsUncopyable(),
- "Expected equality of these values:\n"
- " x\n Which is: 5\n y\n Which is: -1");
-}
-
-// Tests that uncopyable objects can be used in expects.
-TEST(AssertionTest, ExpectWorksWithUncopyableObject) {
- Uncopyable x(5);
- EXPECT_PRED1(IsPositiveUncopyable, x);
- Uncopyable y(-1);
- EXPECT_NONFATAL_FAILURE(EXPECT_PRED1(IsPositiveUncopyable, y),
- "IsPositiveUncopyable(y) evaluates to false, where\ny evaluates to -1");
- EXPECT_EQ(x, x);
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y),
- "Expected equality of these values:\n"
- " x\n Which is: 5\n y\n Which is: -1");
-}
-
-enum NamedEnum {
- kE1 = 0,
- kE2 = 1
-};
-
-TEST(AssertionTest, NamedEnum) {
- EXPECT_EQ(kE1, kE1);
- EXPECT_LT(kE1, kE2);
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 0");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(kE1, kE2), "Which is: 1");
-}
-
-// Sun Studio and HP aCC2reject this code.
-#if !defined(__SUNPRO_CC) && !defined(__HP_aCC)
-
-// Tests using assertions with anonymous enums.
-enum {
- kCaseA = -1,
-
-# if GTEST_OS_LINUX
-
- // We want to test the case where the size of the anonymous enum is
- // larger than sizeof(int), to make sure our implementation of the
- // assertions doesn't truncate the enums. However, MSVC
- // (incorrectly) doesn't allow an enum value to exceed the range of
- // an int, so this has to be conditionally compiled.
- //
- // On Linux, kCaseB and kCaseA have the same value when truncated to
- // int size. We want to test whether this will confuse the
- // assertions.
- kCaseB = testing::internal::kMaxBiggestInt,
-
-# else
-
- kCaseB = INT_MAX,
-
-# endif // GTEST_OS_LINUX
-
- kCaseC = 42
-};
-
-TEST(AssertionTest, AnonymousEnum) {
-# if GTEST_OS_LINUX
-
- EXPECT_EQ(static_cast<int>(kCaseA), static_cast<int>(kCaseB));
-
-# endif // GTEST_OS_LINUX
-
- EXPECT_EQ(kCaseA, kCaseA);
- EXPECT_NE(kCaseA, kCaseB);
- EXPECT_LT(kCaseA, kCaseB);
- EXPECT_LE(kCaseA, kCaseB);
- EXPECT_GT(kCaseB, kCaseA);
- EXPECT_GE(kCaseA, kCaseA);
- EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseB),
- "(kCaseA) >= (kCaseB)");
- EXPECT_NONFATAL_FAILURE(EXPECT_GE(kCaseA, kCaseC),
- "-1 vs 42");
-
- ASSERT_EQ(kCaseA, kCaseA);
- ASSERT_NE(kCaseA, kCaseB);
- ASSERT_LT(kCaseA, kCaseB);
- ASSERT_LE(kCaseA, kCaseB);
- ASSERT_GT(kCaseB, kCaseA);
- ASSERT_GE(kCaseA, kCaseA);
-
-# ifndef __BORLANDC__
-
- // ICE's in C++Builder.
- EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseB),
- " kCaseB\n Which is: ");
- EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
- "\n Which is: 42");
-# endif
-
- EXPECT_FATAL_FAILURE(ASSERT_EQ(kCaseA, kCaseC),
- "\n Which is: -1");
-}
-
-#endif // !GTEST_OS_MAC && !defined(__SUNPRO_CC)
-
-#if GTEST_OS_WINDOWS
-
-static HRESULT UnexpectedHRESULTFailure() {
- return E_UNEXPECTED;
-}
-
-static HRESULT OkHRESULTSuccess() {
- return S_OK;
-}
-
-static HRESULT FalseHRESULTSuccess() {
- return S_FALSE;
-}
-
-// HRESULT assertion tests test both zero and non-zero
-// success codes as well as failure message for each.
-//
-// Windows CE doesn't support message texts.
-TEST(HRESULTAssertionTest, EXPECT_HRESULT_SUCCEEDED) {
- EXPECT_HRESULT_SUCCEEDED(S_OK);
- EXPECT_HRESULT_SUCCEEDED(S_FALSE);
-
- EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
- "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
- " Actual: 0x8000FFFF");
-}
-
-TEST(HRESULTAssertionTest, ASSERT_HRESULT_SUCCEEDED) {
- ASSERT_HRESULT_SUCCEEDED(S_OK);
- ASSERT_HRESULT_SUCCEEDED(S_FALSE);
-
- EXPECT_FATAL_FAILURE(ASSERT_HRESULT_SUCCEEDED(UnexpectedHRESULTFailure()),
- "Expected: (UnexpectedHRESULTFailure()) succeeds.\n"
- " Actual: 0x8000FFFF");
-}
-
-TEST(HRESULTAssertionTest, EXPECT_HRESULT_FAILED) {
- EXPECT_HRESULT_FAILED(E_UNEXPECTED);
-
- EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(OkHRESULTSuccess()),
- "Expected: (OkHRESULTSuccess()) fails.\n"
- " Actual: 0x0");
- EXPECT_NONFATAL_FAILURE(EXPECT_HRESULT_FAILED(FalseHRESULTSuccess()),
- "Expected: (FalseHRESULTSuccess()) fails.\n"
- " Actual: 0x1");
-}
-
-TEST(HRESULTAssertionTest, ASSERT_HRESULT_FAILED) {
- ASSERT_HRESULT_FAILED(E_UNEXPECTED);
-
-# ifndef __BORLANDC__
-
- // ICE's in C++Builder 2007 and 2009.
- EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(OkHRESULTSuccess()),
- "Expected: (OkHRESULTSuccess()) fails.\n"
- " Actual: 0x0");
-# endif
-
- EXPECT_FATAL_FAILURE(ASSERT_HRESULT_FAILED(FalseHRESULTSuccess()),
- "Expected: (FalseHRESULTSuccess()) fails.\n"
- " Actual: 0x1");
-}
-
-// Tests that streaming to the HRESULT macros works.
-TEST(HRESULTAssertionTest, Streaming) {
- EXPECT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
- ASSERT_HRESULT_SUCCEEDED(S_OK) << "unexpected failure";
- EXPECT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
- ASSERT_HRESULT_FAILED(E_UNEXPECTED) << "unexpected failure";
-
- EXPECT_NONFATAL_FAILURE(
- EXPECT_HRESULT_SUCCEEDED(E_UNEXPECTED) << "expected failure",
- "expected failure");
-
-# ifndef __BORLANDC__
-
- // ICE's in C++Builder 2007 and 2009.
- EXPECT_FATAL_FAILURE(
- ASSERT_HRESULT_SUCCEEDED(E_UNEXPECTED) << "expected failure",
- "expected failure");
-# endif
-
- EXPECT_NONFATAL_FAILURE(
- EXPECT_HRESULT_FAILED(S_OK) << "expected failure",
- "expected failure");
-
- EXPECT_FATAL_FAILURE(
- ASSERT_HRESULT_FAILED(S_OK) << "expected failure",
- "expected failure");
-}
-
-#endif // GTEST_OS_WINDOWS
-
-#ifdef __BORLANDC__
-// Silences warnings: "Condition is always true", "Unreachable code"
-# pragma option push -w-ccc -w-rch
-#endif
-
-// Tests that the assertion macros behave like single statements.
-TEST(AssertionSyntaxTest, BasicAssertionsBehavesLikeSingleStatement) {
- if (AlwaysFalse())
- ASSERT_TRUE(false) << "This should never be executed; "
- "It's a compilation test only.";
-
- if (AlwaysTrue())
- EXPECT_FALSE(false);
- else
- ; // NOLINT
-
- if (AlwaysFalse())
- ASSERT_LT(1, 3);
-
- if (AlwaysFalse())
- ; // NOLINT
- else
- EXPECT_GT(3, 2) << "";
-}
-
-#if GTEST_HAS_EXCEPTIONS
-// Tests that the compiler will not complain about unreachable code in the
-// EXPECT_THROW/EXPECT_ANY_THROW/EXPECT_NO_THROW macros.
-TEST(ExpectThrowTest, DoesNotGenerateUnreachableCodeWarning) {
- int n = 0;
-
- EXPECT_THROW(throw 1, int);
- EXPECT_NONFATAL_FAILURE(EXPECT_THROW(n++, int), "");
- EXPECT_NONFATAL_FAILURE(EXPECT_THROW(throw 1, const char*), "");
- EXPECT_NO_THROW(n++);
- EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(throw 1), "");
- EXPECT_ANY_THROW(throw 1);
- EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(n++), "");
-}
-
-TEST(AssertionSyntaxTest, ExceptionAssertionsBehavesLikeSingleStatement) {
- if (AlwaysFalse())
- EXPECT_THROW(ThrowNothing(), bool);
-
- if (AlwaysTrue())
- EXPECT_THROW(ThrowAnInteger(), int);
- else
- ; // NOLINT
-
- if (AlwaysFalse())
- EXPECT_NO_THROW(ThrowAnInteger());
-
- if (AlwaysTrue())
- EXPECT_NO_THROW(ThrowNothing());
- else
- ; // NOLINT
-
- if (AlwaysFalse())
- EXPECT_ANY_THROW(ThrowNothing());
-
- if (AlwaysTrue())
- EXPECT_ANY_THROW(ThrowAnInteger());
- else
- ; // NOLINT
-}
-#endif // GTEST_HAS_EXCEPTIONS
-
-TEST(AssertionSyntaxTest, NoFatalFailureAssertionsBehavesLikeSingleStatement) {
- if (AlwaysFalse())
- EXPECT_NO_FATAL_FAILURE(FAIL()) << "This should never be executed. "
- << "It's a compilation test only.";
- else
- ; // NOLINT
-
- if (AlwaysFalse())
- ASSERT_NO_FATAL_FAILURE(FAIL()) << "";
- else
- ; // NOLINT
-
- if (AlwaysTrue())
- EXPECT_NO_FATAL_FAILURE(SUCCEED());
- else
- ; // NOLINT
-
- if (AlwaysFalse())
- ; // NOLINT
- else
- ASSERT_NO_FATAL_FAILURE(SUCCEED());
-}
-
-// Tests that the assertion macros work well with switch statements.
-TEST(AssertionSyntaxTest, WorksWithSwitch) {
- switch (0) {
- case 1:
- break;
- default:
- ASSERT_TRUE(true);
- }
-
- switch (0)
- case 0:
- EXPECT_FALSE(false) << "EXPECT_FALSE failed in switch case";
-
- // Binary assertions are implemented using a different code path
- // than the Boolean assertions. Hence we test them separately.
- switch (0) {
- case 1:
- default:
- ASSERT_EQ(1, 1) << "ASSERT_EQ failed in default switch handler";
- }
-
- switch (0)
- case 0:
- EXPECT_NE(1, 2);
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-void ThrowAString() {
- throw "std::string";
-}
-
-// Test that the exception assertion macros compile and work with const
-// type qualifier.
-TEST(AssertionSyntaxTest, WorksWithConst) {
- ASSERT_THROW(ThrowAString(), const char*);
-
- EXPECT_THROW(ThrowAString(), const char*);
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-} // namespace
-
-namespace testing {
-
-// Tests that Google Test tracks SUCCEED*.
-TEST(SuccessfulAssertionTest, SUCCEED) {
- SUCCEED();
- SUCCEED() << "OK";
- EXPECT_EQ(2, GetUnitTestImpl()->current_test_result()->total_part_count());
-}
-
-// Tests that Google Test doesn't track successful EXPECT_*.
-TEST(SuccessfulAssertionTest, EXPECT) {
- EXPECT_TRUE(true);
- EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
-}
-
-// Tests that Google Test doesn't track successful EXPECT_STR*.
-TEST(SuccessfulAssertionTest, EXPECT_STR) {
- EXPECT_STREQ("", "");
- EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
-}
-
-// Tests that Google Test doesn't track successful ASSERT_*.
-TEST(SuccessfulAssertionTest, ASSERT) {
- ASSERT_TRUE(true);
- EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
-}
-
-// Tests that Google Test doesn't track successful ASSERT_STR*.
-TEST(SuccessfulAssertionTest, ASSERT_STR) {
- ASSERT_STREQ("", "");
- EXPECT_EQ(0, GetUnitTestImpl()->current_test_result()->total_part_count());
-}
-
-} // namespace testing
-
-namespace {
-
-// Tests the message streaming variation of assertions.
-
-TEST(AssertionWithMessageTest, EXPECT) {
- EXPECT_EQ(1, 1) << "This should succeed.";
- EXPECT_NONFATAL_FAILURE(EXPECT_NE(1, 1) << "Expected failure #1.",
- "Expected failure #1");
- EXPECT_LE(1, 2) << "This should succeed.";
- EXPECT_NONFATAL_FAILURE(EXPECT_LT(1, 0) << "Expected failure #2.",
- "Expected failure #2.");
- EXPECT_GE(1, 0) << "This should succeed.";
- EXPECT_NONFATAL_FAILURE(EXPECT_GT(1, 2) << "Expected failure #3.",
- "Expected failure #3.");
-
- EXPECT_STREQ("1", "1") << "This should succeed.";
- EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("1", "1") << "Expected failure #4.",
- "Expected failure #4.");
- EXPECT_STRCASEEQ("a", "A") << "This should succeed.";
- EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("a", "A") << "Expected failure #5.",
- "Expected failure #5.");
-
- EXPECT_FLOAT_EQ(1, 1) << "This should succeed.";
- EXPECT_NONFATAL_FAILURE(EXPECT_DOUBLE_EQ(1, 1.2) << "Expected failure #6.",
- "Expected failure #6.");
- EXPECT_NEAR(1, 1.1, 0.2) << "This should succeed.";
-}
-
-TEST(AssertionWithMessageTest, ASSERT) {
- ASSERT_EQ(1, 1) << "This should succeed.";
- ASSERT_NE(1, 2) << "This should succeed.";
- ASSERT_LE(1, 2) << "This should succeed.";
- ASSERT_LT(1, 2) << "This should succeed.";
- ASSERT_GE(1, 0) << "This should succeed.";
- EXPECT_FATAL_FAILURE(ASSERT_GT(1, 2) << "Expected failure.",
- "Expected failure.");
-}
-
-TEST(AssertionWithMessageTest, ASSERT_STR) {
- ASSERT_STREQ("1", "1") << "This should succeed.";
- ASSERT_STRNE("1", "2") << "This should succeed.";
- ASSERT_STRCASEEQ("a", "A") << "This should succeed.";
- EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("a", "A") << "Expected failure.",
- "Expected failure.");
-}
-
-TEST(AssertionWithMessageTest, ASSERT_FLOATING) {
- ASSERT_FLOAT_EQ(1, 1) << "This should succeed.";
- ASSERT_DOUBLE_EQ(1, 1) << "This should succeed.";
- EXPECT_FATAL_FAILURE(ASSERT_NEAR(1,1.2, 0.1) << "Expect failure.", // NOLINT
- "Expect failure.");
- // To work around a bug in gcc 2.95.0, there is intentionally no
- // space after the first comma in the previous statement.
-}
-
-// Tests using ASSERT_FALSE with a streamed message.
-TEST(AssertionWithMessageTest, ASSERT_FALSE) {
- ASSERT_FALSE(false) << "This shouldn't fail.";
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_FALSE(true) << "Expected failure: " << 2 << " > " << 1
- << " evaluates to " << true;
- }, "Expected failure");
-}
-
-// Tests using FAIL with a streamed message.
-TEST(AssertionWithMessageTest, FAIL) {
- EXPECT_FATAL_FAILURE(FAIL() << 0,
- "0");
-}
-
-// Tests using SUCCEED with a streamed message.
-TEST(AssertionWithMessageTest, SUCCEED) {
- SUCCEED() << "Success == " << 1;
-}
-
-// Tests using ASSERT_TRUE with a streamed message.
-TEST(AssertionWithMessageTest, ASSERT_TRUE) {
- ASSERT_TRUE(true) << "This should succeed.";
- ASSERT_TRUE(true) << true;
- EXPECT_FATAL_FAILURE(
- { // NOLINT
- ASSERT_TRUE(false) << static_cast<const char*>(nullptr)
- << static_cast<char*>(nullptr);
- },
- "(null)(null)");
-}
-
-#if GTEST_OS_WINDOWS
-// Tests using wide strings in assertion messages.
-TEST(AssertionWithMessageTest, WideStringMessage) {
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_TRUE(false) << L"This failure is expected.\x8119";
- }, "This failure is expected.");
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_EQ(1, 2) << "This failure is "
- << L"expected too.\x8120";
- }, "This failure is expected too.");
-}
-#endif // GTEST_OS_WINDOWS
-
-// Tests EXPECT_TRUE.
-TEST(ExpectTest, EXPECT_TRUE) {
- EXPECT_TRUE(true) << "Intentional success";
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "Intentional failure #1.",
- "Intentional failure #1.");
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "Intentional failure #2.",
- "Intentional failure #2.");
- EXPECT_TRUE(2 > 1); // NOLINT
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 < 1),
- "Value of: 2 < 1\n"
- " Actual: false\n"
- "Expected: true");
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(2 > 3),
- "2 > 3");
-}
-
-// Tests EXPECT_TRUE(predicate) for predicates returning AssertionResult.
-TEST(ExpectTest, ExpectTrueWithAssertionResult) {
- EXPECT_TRUE(ResultIsEven(2));
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEven(3)),
- "Value of: ResultIsEven(3)\n"
- " Actual: false (3 is odd)\n"
- "Expected: true");
- EXPECT_TRUE(ResultIsEvenNoExplanation(2));
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(ResultIsEvenNoExplanation(3)),
- "Value of: ResultIsEvenNoExplanation(3)\n"
- " Actual: false (3 is odd)\n"
- "Expected: true");
-}
-
-// Tests EXPECT_FALSE with a streamed message.
-TEST(ExpectTest, EXPECT_FALSE) {
- EXPECT_FALSE(2 < 1); // NOLINT
- EXPECT_FALSE(false) << "Intentional success";
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "Intentional failure #1.",
- "Intentional failure #1.");
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "Intentional failure #2.",
- "Intentional failure #2.");
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 > 1),
- "Value of: 2 > 1\n"
- " Actual: true\n"
- "Expected: false");
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(2 < 3),
- "2 < 3");
-}
-
-// Tests EXPECT_FALSE(predicate) for predicates returning AssertionResult.
-TEST(ExpectTest, ExpectFalseWithAssertionResult) {
- EXPECT_FALSE(ResultIsEven(3));
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEven(2)),
- "Value of: ResultIsEven(2)\n"
- " Actual: true (2 is even)\n"
- "Expected: false");
- EXPECT_FALSE(ResultIsEvenNoExplanation(3));
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(ResultIsEvenNoExplanation(2)),
- "Value of: ResultIsEvenNoExplanation(2)\n"
- " Actual: true\n"
- "Expected: false");
-}
-
-#ifdef __BORLANDC__
-// Restores warnings after previous "#pragma option push" suppressed them
-# pragma option pop
-#endif
-
-// Tests EXPECT_EQ.
-TEST(ExpectTest, EXPECT_EQ) {
- EXPECT_EQ(5, 2 + 3);
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2*3),
- "Expected equality of these values:\n"
- " 5\n"
- " 2*3\n"
- " Which is: 6");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5, 2 - 3),
- "2 - 3");
-}
-
-// Tests using EXPECT_EQ on double values. The purpose is to make
-// sure that the specialization we did for integer and anonymous enums
-// isn't used for double arguments.
-TEST(ExpectTest, EXPECT_EQ_Double) {
- // A success.
- EXPECT_EQ(5.6, 5.6);
-
- // A failure.
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(5.1, 5.2),
- "5.1");
-}
-
-// Tests EXPECT_EQ(NULL, pointer).
-TEST(ExpectTest, EXPECT_EQ_NULL) {
- // A success.
- const char* p = nullptr;
- // Some older GCC versions may issue a spurious warning in this or the next
- // assertion statement. This warning should not be suppressed with
- // static_cast since the test verifies the ability to use bare NULL as the
- // expected parameter to the macro.
- EXPECT_EQ(nullptr, p);
-
- // A failure.
- int n = 0;
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(nullptr, &n), " &n\n Which is:");
-}
-
-// Tests EXPECT_EQ(0, non_pointer). Since the literal 0 can be
-// treated as a null pointer by the compiler, we need to make sure
-// that EXPECT_EQ(0, non_pointer) isn't interpreted by Google Test as
-// EXPECT_EQ(static_cast<void*>(NULL), non_pointer).
-TEST(ExpectTest, EXPECT_EQ_0) {
- int n = 0;
-
- // A success.
- EXPECT_EQ(0, n);
-
- // A failure.
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(0, 5.6),
- " 0\n 5.6");
-}
-
-// Tests EXPECT_NE.
-TEST(ExpectTest, EXPECT_NE) {
- EXPECT_NE(6, 7);
-
- EXPECT_NONFATAL_FAILURE(EXPECT_NE('a', 'a'),
- "Expected: ('a') != ('a'), "
- "actual: 'a' (97, 0x61) vs 'a' (97, 0x61)");
- EXPECT_NONFATAL_FAILURE(EXPECT_NE(2, 2),
- "2");
- char* const p0 = nullptr;
- EXPECT_NONFATAL_FAILURE(EXPECT_NE(p0, p0),
- "p0");
- // Only way to get the Nokia compiler to compile the cast
- // is to have a separate void* variable first. Putting
- // the two casts on the same line doesn't work, neither does
- // a direct C-style to char*.
- void* pv1 = (void*)0x1234; // NOLINT
- char* const p1 = reinterpret_cast<char*>(pv1);
- EXPECT_NONFATAL_FAILURE(EXPECT_NE(p1, p1),
- "p1");
-}
-
-// Tests EXPECT_LE.
-TEST(ExpectTest, EXPECT_LE) {
- EXPECT_LE(2, 3);
- EXPECT_LE(2, 2);
- EXPECT_NONFATAL_FAILURE(EXPECT_LE(2, 0),
- "Expected: (2) <= (0), actual: 2 vs 0");
- EXPECT_NONFATAL_FAILURE(EXPECT_LE(1.1, 0.9),
- "(1.1) <= (0.9)");
-}
-
-// Tests EXPECT_LT.
-TEST(ExpectTest, EXPECT_LT) {
- EXPECT_LT(2, 3);
- EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 2),
- "Expected: (2) < (2), actual: 2 vs 2");
- EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1),
- "(2) < (1)");
-}
-
-// Tests EXPECT_GE.
-TEST(ExpectTest, EXPECT_GE) {
- EXPECT_GE(2, 1);
- EXPECT_GE(2, 2);
- EXPECT_NONFATAL_FAILURE(EXPECT_GE(2, 3),
- "Expected: (2) >= (3), actual: 2 vs 3");
- EXPECT_NONFATAL_FAILURE(EXPECT_GE(0.9, 1.1),
- "(0.9) >= (1.1)");
-}
-
-// Tests EXPECT_GT.
-TEST(ExpectTest, EXPECT_GT) {
- EXPECT_GT(2, 1);
- EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 2),
- "Expected: (2) > (2), actual: 2 vs 2");
- EXPECT_NONFATAL_FAILURE(EXPECT_GT(2, 3),
- "(2) > (3)");
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-// Tests EXPECT_THROW.
-TEST(ExpectTest, EXPECT_THROW) {
- EXPECT_THROW(ThrowAnInteger(), int);
- EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool),
- "Expected: ThrowAnInteger() throws an exception of "
- "type bool.\n Actual: it throws a different type.");
- EXPECT_NONFATAL_FAILURE(
- EXPECT_THROW(ThrowNothing(), bool),
- "Expected: ThrowNothing() throws an exception of type bool.\n"
- " Actual: it throws nothing.");
-}
-
-// Tests EXPECT_NO_THROW.
-TEST(ExpectTest, EXPECT_NO_THROW) {
- EXPECT_NO_THROW(ThrowNothing());
- EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()),
- "Expected: ThrowAnInteger() doesn't throw an "
- "exception.\n Actual: it throws.");
-}
-
-// Tests EXPECT_ANY_THROW.
-TEST(ExpectTest, EXPECT_ANY_THROW) {
- EXPECT_ANY_THROW(ThrowAnInteger());
- EXPECT_NONFATAL_FAILURE(
- EXPECT_ANY_THROW(ThrowNothing()),
- "Expected: ThrowNothing() throws an exception.\n"
- " Actual: it doesn't.");
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// Make sure we deal with the precedence of <<.
-TEST(ExpectTest, ExpectPrecedence) {
- EXPECT_EQ(1 < 2, true);
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(true, true && false),
- " true && false\n Which is: false");
-}
-
-
-// Tests the StreamableToString() function.
-
-// Tests using StreamableToString() on a scalar.
-TEST(StreamableToStringTest, Scalar) {
- EXPECT_STREQ("5", StreamableToString(5).c_str());
-}
-
-// Tests using StreamableToString() on a non-char pointer.
-TEST(StreamableToStringTest, Pointer) {
- int n = 0;
- int* p = &n;
- EXPECT_STRNE("(null)", StreamableToString(p).c_str());
-}
-
-// Tests using StreamableToString() on a NULL non-char pointer.
-TEST(StreamableToStringTest, NullPointer) {
- int* p = nullptr;
- EXPECT_STREQ("(null)", StreamableToString(p).c_str());
-}
-
-// Tests using StreamableToString() on a C string.
-TEST(StreamableToStringTest, CString) {
- EXPECT_STREQ("Foo", StreamableToString("Foo").c_str());
-}
-
-// Tests using StreamableToString() on a NULL C string.
-TEST(StreamableToStringTest, NullCString) {
- char* p = nullptr;
- EXPECT_STREQ("(null)", StreamableToString(p).c_str());
-}
-
-// Tests using streamable values as assertion messages.
-
-// Tests using std::string as an assertion message.
-TEST(StreamableTest, string) {
- static const std::string str(
- "This failure message is a std::string, and is expected.");
- EXPECT_FATAL_FAILURE(FAIL() << str,
- str.c_str());
-}
-
-// Tests that we can output strings containing embedded NULs.
-// Limited to Linux because we can only do this with std::string's.
-TEST(StreamableTest, stringWithEmbeddedNUL) {
- static const char char_array_with_nul[] =
- "Here's a NUL\0 and some more string";
- static const std::string string_with_nul(char_array_with_nul,
- sizeof(char_array_with_nul)
- - 1); // drops the trailing NUL
- EXPECT_FATAL_FAILURE(FAIL() << string_with_nul,
- "Here's a NUL\\0 and some more string");
-}
-
-// Tests that we can output a NUL char.
-TEST(StreamableTest, NULChar) {
- EXPECT_FATAL_FAILURE({ // NOLINT
- FAIL() << "A NUL" << '\0' << " and some more string";
- }, "A NUL\\0 and some more string");
-}
-
-// Tests using int as an assertion message.
-TEST(StreamableTest, int) {
- EXPECT_FATAL_FAILURE(FAIL() << 900913,
- "900913");
-}
-
-// Tests using NULL char pointer as an assertion message.
-//
-// In MSVC, streaming a NULL char * causes access violation. Google Test
-// implemented a workaround (substituting "(null)" for NULL). This
-// tests whether the workaround works.
-TEST(StreamableTest, NullCharPtr) {
- EXPECT_FATAL_FAILURE(FAIL() << static_cast<const char*>(nullptr), "(null)");
-}
-
-// Tests that basic IO manipulators (endl, ends, and flush) can be
-// streamed to testing::Message.
-TEST(StreamableTest, BasicIoManip) {
- EXPECT_FATAL_FAILURE({ // NOLINT
- FAIL() << "Line 1." << std::endl
- << "A NUL char " << std::ends << std::flush << " in line 2.";
- }, "Line 1.\nA NUL char \\0 in line 2.");
-}
-
-// Tests the macros that haven't been covered so far.
-
-void AddFailureHelper(bool* aborted) {
- *aborted = true;
- ADD_FAILURE() << "Intentional failure.";
- *aborted = false;
-}
-
-// Tests ADD_FAILURE.
-TEST(MacroTest, ADD_FAILURE) {
- bool aborted = true;
- EXPECT_NONFATAL_FAILURE(AddFailureHelper(&aborted),
- "Intentional failure.");
- EXPECT_FALSE(aborted);
-}
-
-// Tests ADD_FAILURE_AT.
-TEST(MacroTest, ADD_FAILURE_AT) {
- // Verifies that ADD_FAILURE_AT does generate a nonfatal failure and
- // the failure message contains the user-streamed part.
- EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42) << "Wrong!", "Wrong!");
-
- // Verifies that the user-streamed part is optional.
- EXPECT_NONFATAL_FAILURE(ADD_FAILURE_AT("foo.cc", 42), "Failed");
-
- // Unfortunately, we cannot verify that the failure message contains
- // the right file path and line number the same way, as
- // EXPECT_NONFATAL_FAILURE() doesn't get to see the file path and
- // line number. Instead, we do that in googletest-output-test_.cc.
-}
-
-// Tests FAIL.
-TEST(MacroTest, FAIL) {
- EXPECT_FATAL_FAILURE(FAIL(),
- "Failed");
- EXPECT_FATAL_FAILURE(FAIL() << "Intentional failure.",
- "Intentional failure.");
-}
-
-// Tests GTEST_FAIL_AT.
-TEST(MacroTest, GTEST_FAIL_AT) {
- // Verifies that GTEST_FAIL_AT does generate a fatal failure and
- // the failure message contains the user-streamed part.
- EXPECT_FATAL_FAILURE(GTEST_FAIL_AT("foo.cc", 42) << "Wrong!", "Wrong!");
-
- // Verifies that the user-streamed part is optional.
- EXPECT_FATAL_FAILURE(GTEST_FAIL_AT("foo.cc", 42), "Failed");
-
- // See the ADD_FAIL_AT test above to see how we test that the failure message
- // contains the right filename and line number -- the same applies here.
-}
-
-// Tests SUCCEED
-TEST(MacroTest, SUCCEED) {
- SUCCEED();
- SUCCEED() << "Explicit success.";
-}
-
-// Tests for EXPECT_EQ() and ASSERT_EQ().
-//
-// These tests fail *intentionally*, s.t. the failure messages can be
-// generated and tested.
-//
-// We have different tests for different argument types.
-
-// Tests using bool values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, Bool) {
- EXPECT_EQ(true, true);
- EXPECT_FATAL_FAILURE({
- bool false_value = false;
- ASSERT_EQ(false_value, true);
- }, " false_value\n Which is: false\n true");
-}
-
-// Tests using int values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, Int) {
- ASSERT_EQ(32, 32);
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(32, 33),
- " 32\n 33");
-}
-
-// Tests using time_t values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, Time_T) {
- EXPECT_EQ(static_cast<time_t>(0),
- static_cast<time_t>(0));
- EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<time_t>(0),
- static_cast<time_t>(1234)),
- "1234");
-}
-
-// Tests using char values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, Char) {
- ASSERT_EQ('z', 'z');
- const char ch = 'b';
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ('\0', ch),
- " ch\n Which is: 'b'");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ('a', ch),
- " ch\n Which is: 'b'");
-}
-
-// Tests using wchar_t values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, WideChar) {
- EXPECT_EQ(L'b', L'b');
-
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'\0', L'x'),
- "Expected equality of these values:\n"
- " L'\0'\n"
- " Which is: L'\0' (0, 0x0)\n"
- " L'x'\n"
- " Which is: L'x' (120, 0x78)");
-
- static wchar_t wchar;
- wchar = L'b';
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(L'a', wchar),
- "wchar");
- wchar = 0x8119;
- EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<wchar_t>(0x8120), wchar),
- " wchar\n Which is: L'");
-}
-
-// Tests using ::std::string values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, StdString) {
- // Compares a const char* to an std::string that has identical
- // content.
- ASSERT_EQ("Test", ::std::string("Test"));
-
- // Compares two identical std::strings.
- static const ::std::string str1("A * in the middle");
- static const ::std::string str2(str1);
- EXPECT_EQ(str1, str2);
-
- // Compares a const char* to an std::string that has different
- // content
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ("Test", ::std::string("test")),
- "\"test\"");
-
- // Compares an std::string to a char* that has different content.
- char* const p1 = const_cast<char*>("foo");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(::std::string("bar"), p1),
- "p1");
-
- // Compares two std::strings that have different contents, one of
- // which having a NUL character in the middle. This should fail.
- static ::std::string str3(str1);
- str3.at(2) = '\0';
- EXPECT_FATAL_FAILURE(ASSERT_EQ(str1, str3),
- " str3\n Which is: \"A \\0 in the middle\"");
-}
-
-#if GTEST_HAS_STD_WSTRING
-
-// Tests using ::std::wstring values in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, StdWideString) {
- // Compares two identical std::wstrings.
- const ::std::wstring wstr1(L"A * in the middle");
- const ::std::wstring wstr2(wstr1);
- ASSERT_EQ(wstr1, wstr2);
-
- // Compares an std::wstring to a const wchar_t* that has identical
- // content.
- const wchar_t kTestX8119[] = { 'T', 'e', 's', 't', 0x8119, '\0' };
- EXPECT_EQ(::std::wstring(kTestX8119), kTestX8119);
-
- // Compares an std::wstring to a const wchar_t* that has different
- // content.
- const wchar_t kTestX8120[] = { 'T', 'e', 's', 't', 0x8120, '\0' };
- EXPECT_NONFATAL_FAILURE({ // NOLINT
- EXPECT_EQ(::std::wstring(kTestX8119), kTestX8120);
- }, "kTestX8120");
-
- // Compares two std::wstrings that have different contents, one of
- // which having a NUL character in the middle.
- ::std::wstring wstr3(wstr1);
- wstr3.at(2) = L'\0';
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(wstr1, wstr3),
- "wstr3");
-
- // Compares a wchar_t* to an std::wstring that has different
- // content.
- EXPECT_FATAL_FAILURE({ // NOLINT
- ASSERT_EQ(const_cast<wchar_t*>(L"foo"), ::std::wstring(L"bar"));
- }, "");
-}
-
-#endif // GTEST_HAS_STD_WSTRING
-
-// Tests using char pointers in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, CharPointer) {
- char* const p0 = nullptr;
- // Only way to get the Nokia compiler to compile the cast
- // is to have a separate void* variable first. Putting
- // the two casts on the same line doesn't work, neither does
- // a direct C-style to char*.
- void* pv1 = (void*)0x1234; // NOLINT
- void* pv2 = (void*)0xABC0; // NOLINT
- char* const p1 = reinterpret_cast<char*>(pv1);
- char* const p2 = reinterpret_cast<char*>(pv2);
- ASSERT_EQ(p1, p1);
-
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
- " p2\n Which is:");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
- " p2\n Which is:");
- EXPECT_FATAL_FAILURE(ASSERT_EQ(reinterpret_cast<char*>(0x1234),
- reinterpret_cast<char*>(0xABC0)),
- "ABC0");
-}
-
-// Tests using wchar_t pointers in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, WideCharPointer) {
- wchar_t* const p0 = nullptr;
- // Only way to get the Nokia compiler to compile the cast
- // is to have a separate void* variable first. Putting
- // the two casts on the same line doesn't work, neither does
- // a direct C-style to char*.
- void* pv1 = (void*)0x1234; // NOLINT
- void* pv2 = (void*)0xABC0; // NOLINT
- wchar_t* const p1 = reinterpret_cast<wchar_t*>(pv1);
- wchar_t* const p2 = reinterpret_cast<wchar_t*>(pv2);
- EXPECT_EQ(p0, p0);
-
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p0, p2),
- " p2\n Which is:");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p1, p2),
- " p2\n Which is:");
- void* pv3 = (void*)0x1234; // NOLINT
- void* pv4 = (void*)0xABC0; // NOLINT
- const wchar_t* p3 = reinterpret_cast<const wchar_t*>(pv3);
- const wchar_t* p4 = reinterpret_cast<const wchar_t*>(pv4);
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(p3, p4),
- "p4");
-}
-
-// Tests using other types of pointers in {EXPECT|ASSERT}_EQ.
-TEST(EqAssertionTest, OtherPointer) {
- ASSERT_EQ(static_cast<const int*>(nullptr), static_cast<const int*>(nullptr));
- EXPECT_FATAL_FAILURE(ASSERT_EQ(static_cast<const int*>(nullptr),
- reinterpret_cast<const int*>(0x1234)),
- "0x1234");
-}
-
-// A class that supports binary comparison operators but not streaming.
-class UnprintableChar {
- public:
- explicit UnprintableChar(char ch) : char_(ch) {}
-
- bool operator==(const UnprintableChar& rhs) const {
- return char_ == rhs.char_;
- }
- bool operator!=(const UnprintableChar& rhs) const {
- return char_ != rhs.char_;
- }
- bool operator<(const UnprintableChar& rhs) const {
- return char_ < rhs.char_;
- }
- bool operator<=(const UnprintableChar& rhs) const {
- return char_ <= rhs.char_;
- }
- bool operator>(const UnprintableChar& rhs) const {
- return char_ > rhs.char_;
- }
- bool operator>=(const UnprintableChar& rhs) const {
- return char_ >= rhs.char_;
- }
-
- private:
- char char_;
-};
-
-// Tests that ASSERT_EQ() and friends don't require the arguments to
-// be printable.
-TEST(ComparisonAssertionTest, AcceptsUnprintableArgs) {
- const UnprintableChar x('x'), y('y');
- ASSERT_EQ(x, x);
- EXPECT_NE(x, y);
- ASSERT_LT(x, y);
- EXPECT_LE(x, y);
- ASSERT_GT(y, x);
- EXPECT_GE(x, x);
-
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <78>");
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(x, y), "1-byte object <79>");
- EXPECT_NONFATAL_FAILURE(EXPECT_LT(y, y), "1-byte object <79>");
- EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <78>");
- EXPECT_NONFATAL_FAILURE(EXPECT_GT(x, y), "1-byte object <79>");
-
- // Code tested by EXPECT_FATAL_FAILURE cannot reference local
- // variables, so we have to write UnprintableChar('x') instead of x.
-#ifndef __BORLANDC__
- // ICE's in C++Builder.
- EXPECT_FATAL_FAILURE(ASSERT_NE(UnprintableChar('x'), UnprintableChar('x')),
- "1-byte object <78>");
- EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
- "1-byte object <78>");
-#endif
- EXPECT_FATAL_FAILURE(ASSERT_LE(UnprintableChar('y'), UnprintableChar('x')),
- "1-byte object <79>");
- EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
- "1-byte object <78>");
- EXPECT_FATAL_FAILURE(ASSERT_GE(UnprintableChar('x'), UnprintableChar('y')),
- "1-byte object <79>");
-}
-
-// Tests the FRIEND_TEST macro.
-
-// This class has a private member we want to test. We will test it
-// both in a TEST and in a TEST_F.
-class Foo {
- public:
- Foo() {}
-
- private:
- int Bar() const { return 1; }
-
- // Declares the friend tests that can access the private member
- // Bar().
- FRIEND_TEST(FRIEND_TEST_Test, TEST);
- FRIEND_TEST(FRIEND_TEST_Test2, TEST_F);
-};
-
-// Tests that the FRIEND_TEST declaration allows a TEST to access a
-// class's private members. This should compile.
-TEST(FRIEND_TEST_Test, TEST) {
- ASSERT_EQ(1, Foo().Bar());
-}
-
-// The fixture needed to test using FRIEND_TEST with TEST_F.
-class FRIEND_TEST_Test2 : public Test {
- protected:
- Foo foo;
-};
-
-// Tests that the FRIEND_TEST declaration allows a TEST_F to access a
-// class's private members. This should compile.
-TEST_F(FRIEND_TEST_Test2, TEST_F) {
- ASSERT_EQ(1, foo.Bar());
-}
-
-// Tests the life cycle of Test objects.
-
-// The test fixture for testing the life cycle of Test objects.
-//
-// This class counts the number of live test objects that uses this
-// fixture.
-class TestLifeCycleTest : public Test {
- protected:
- // Constructor. Increments the number of test objects that uses
- // this fixture.
- TestLifeCycleTest() { count_++; }
-
- // Destructor. Decrements the number of test objects that uses this
- // fixture.
- ~TestLifeCycleTest() override { count_--; }
-
- // Returns the number of live test objects that uses this fixture.
- int count() const { return count_; }
-
- private:
- static int count_;
-};
-
-int TestLifeCycleTest::count_ = 0;
-
-// Tests the life cycle of test objects.
-TEST_F(TestLifeCycleTest, Test1) {
- // There should be only one test object in this test case that's
- // currently alive.
- ASSERT_EQ(1, count());
-}
-
-// Tests the life cycle of test objects.
-TEST_F(TestLifeCycleTest, Test2) {
- // After Test1 is done and Test2 is started, there should still be
- // only one live test object, as the object for Test1 should've been
- // deleted.
- ASSERT_EQ(1, count());
-}
-
-} // namespace
-
-// Tests that the copy constructor works when it is NOT optimized away by
-// the compiler.
-TEST(AssertionResultTest, CopyConstructorWorksWhenNotOptimied) {
- // Checks that the copy constructor doesn't try to dereference NULL pointers
- // in the source object.
- AssertionResult r1 = AssertionSuccess();
- AssertionResult r2 = r1;
- // The following line is added to prevent the compiler from optimizing
- // away the constructor call.
- r1 << "abc";
-
- AssertionResult r3 = r1;
- EXPECT_EQ(static_cast<bool>(r3), static_cast<bool>(r1));
- EXPECT_STREQ("abc", r1.message());
-}
-
-// Tests that AssertionSuccess and AssertionFailure construct
-// AssertionResult objects as expected.
-TEST(AssertionResultTest, ConstructionWorks) {
- AssertionResult r1 = AssertionSuccess();
- EXPECT_TRUE(r1);
- EXPECT_STREQ("", r1.message());
-
- AssertionResult r2 = AssertionSuccess() << "abc";
- EXPECT_TRUE(r2);
- EXPECT_STREQ("abc", r2.message());
-
- AssertionResult r3 = AssertionFailure();
- EXPECT_FALSE(r3);
- EXPECT_STREQ("", r3.message());
-
- AssertionResult r4 = AssertionFailure() << "def";
- EXPECT_FALSE(r4);
- EXPECT_STREQ("def", r4.message());
-
- AssertionResult r5 = AssertionFailure(Message() << "ghi");
- EXPECT_FALSE(r5);
- EXPECT_STREQ("ghi", r5.message());
-}
-
-// Tests that the negation flips the predicate result but keeps the message.
-TEST(AssertionResultTest, NegationWorks) {
- AssertionResult r1 = AssertionSuccess() << "abc";
- EXPECT_FALSE(!r1);
- EXPECT_STREQ("abc", (!r1).message());
-
- AssertionResult r2 = AssertionFailure() << "def";
- EXPECT_TRUE(!r2);
- EXPECT_STREQ("def", (!r2).message());
-}
-
-TEST(AssertionResultTest, StreamingWorks) {
- AssertionResult r = AssertionSuccess();
- r << "abc" << 'd' << 0 << true;
- EXPECT_STREQ("abcd0true", r.message());
-}
-
-TEST(AssertionResultTest, CanStreamOstreamManipulators) {
- AssertionResult r = AssertionSuccess();
- r << "Data" << std::endl << std::flush << std::ends << "Will be visible";
- EXPECT_STREQ("Data\n\\0Will be visible", r.message());
-}
-
-// The next test uses explicit conversion operators
-
-TEST(AssertionResultTest, ConstructibleFromContextuallyConvertibleToBool) {
- struct ExplicitlyConvertibleToBool {
- explicit operator bool() const { return value; }
- bool value;
- };
- ExplicitlyConvertibleToBool v1 = {false};
- ExplicitlyConvertibleToBool v2 = {true};
- EXPECT_FALSE(v1);
- EXPECT_TRUE(v2);
-}
-
-struct ConvertibleToAssertionResult {
- operator AssertionResult() const { return AssertionResult(true); }
-};
-
-TEST(AssertionResultTest, ConstructibleFromImplicitlyConvertible) {
- ConvertibleToAssertionResult obj;
- EXPECT_TRUE(obj);
-}
-
-// Tests streaming a user type whose definition and operator << are
-// both in the global namespace.
-class Base {
- public:
- explicit Base(int an_x) : x_(an_x) {}
- int x() const { return x_; }
- private:
- int x_;
-};
-std::ostream& operator<<(std::ostream& os,
- const Base& val) {
- return os << val.x();
-}
-std::ostream& operator<<(std::ostream& os,
- const Base* pointer) {
- return os << "(" << pointer->x() << ")";
-}
-
-TEST(MessageTest, CanStreamUserTypeInGlobalNameSpace) {
- Message msg;
- Base a(1);
-
- msg << a << &a; // Uses ::operator<<.
- EXPECT_STREQ("1(1)", msg.GetString().c_str());
-}
-
-// Tests streaming a user type whose definition and operator<< are
-// both in an unnamed namespace.
-namespace {
-class MyTypeInUnnamedNameSpace : public Base {
- public:
- explicit MyTypeInUnnamedNameSpace(int an_x): Base(an_x) {}
-};
-std::ostream& operator<<(std::ostream& os,
- const MyTypeInUnnamedNameSpace& val) {
- return os << val.x();
-}
-std::ostream& operator<<(std::ostream& os,
- const MyTypeInUnnamedNameSpace* pointer) {
- return os << "(" << pointer->x() << ")";
-}
-} // namespace
-
-TEST(MessageTest, CanStreamUserTypeInUnnamedNameSpace) {
- Message msg;
- MyTypeInUnnamedNameSpace a(1);
-
- msg << a << &a; // Uses <unnamed_namespace>::operator<<.
- EXPECT_STREQ("1(1)", msg.GetString().c_str());
-}
-
-// Tests streaming a user type whose definition and operator<< are
-// both in a user namespace.
-namespace namespace1 {
-class MyTypeInNameSpace1 : public Base {
- public:
- explicit MyTypeInNameSpace1(int an_x): Base(an_x) {}
-};
-std::ostream& operator<<(std::ostream& os,
- const MyTypeInNameSpace1& val) {
- return os << val.x();
-}
-std::ostream& operator<<(std::ostream& os,
- const MyTypeInNameSpace1* pointer) {
- return os << "(" << pointer->x() << ")";
-}
-} // namespace namespace1
-
-TEST(MessageTest, CanStreamUserTypeInUserNameSpace) {
- Message msg;
- namespace1::MyTypeInNameSpace1 a(1);
-
- msg << a << &a; // Uses namespace1::operator<<.
- EXPECT_STREQ("1(1)", msg.GetString().c_str());
-}
-
-// Tests streaming a user type whose definition is in a user namespace
-// but whose operator<< is in the global namespace.
-namespace namespace2 {
-class MyTypeInNameSpace2 : public ::Base {
- public:
- explicit MyTypeInNameSpace2(int an_x): Base(an_x) {}
-};
-} // namespace namespace2
-std::ostream& operator<<(std::ostream& os,
- const namespace2::MyTypeInNameSpace2& val) {
- return os << val.x();
-}
-std::ostream& operator<<(std::ostream& os,
- const namespace2::MyTypeInNameSpace2* pointer) {
- return os << "(" << pointer->x() << ")";
-}
-
-TEST(MessageTest, CanStreamUserTypeInUserNameSpaceWithStreamOperatorInGlobal) {
- Message msg;
- namespace2::MyTypeInNameSpace2 a(1);
-
- msg << a << &a; // Uses ::operator<<.
- EXPECT_STREQ("1(1)", msg.GetString().c_str());
-}
-
-// Tests streaming NULL pointers to testing::Message.
-TEST(MessageTest, NullPointers) {
- Message msg;
- char* const p1 = nullptr;
- unsigned char* const p2 = nullptr;
- int* p3 = nullptr;
- double* p4 = nullptr;
- bool* p5 = nullptr;
- Message* p6 = nullptr;
-
- msg << p1 << p2 << p3 << p4 << p5 << p6;
- ASSERT_STREQ("(null)(null)(null)(null)(null)(null)",
- msg.GetString().c_str());
-}
-
-// Tests streaming wide strings to testing::Message.
-TEST(MessageTest, WideStrings) {
- // Streams a NULL of type const wchar_t*.
- const wchar_t* const_wstr = nullptr;
- EXPECT_STREQ("(null)",
- (Message() << const_wstr).GetString().c_str());
-
- // Streams a NULL of type wchar_t*.
- wchar_t* wstr = nullptr;
- EXPECT_STREQ("(null)",
- (Message() << wstr).GetString().c_str());
-
- // Streams a non-NULL of type const wchar_t*.
- const_wstr = L"abc\x8119";
- EXPECT_STREQ("abc\xe8\x84\x99",
- (Message() << const_wstr).GetString().c_str());
-
- // Streams a non-NULL of type wchar_t*.
- wstr = const_cast<wchar_t*>(const_wstr);
- EXPECT_STREQ("abc\xe8\x84\x99",
- (Message() << wstr).GetString().c_str());
-}
-
-
-// This line tests that we can define tests in the testing namespace.
-namespace testing {
-
-// Tests the TestInfo class.
-
-class TestInfoTest : public Test {
- protected:
- static const TestInfo* GetTestInfo(const char* test_name) {
- const TestSuite* const test_suite =
- GetUnitTestImpl()->GetTestSuite("TestInfoTest", "", nullptr, nullptr);
-
- for (int i = 0; i < test_suite->total_test_count(); ++i) {
- const TestInfo* const test_info = test_suite->GetTestInfo(i);
- if (strcmp(test_name, test_info->name()) == 0)
- return test_info;
- }
- return nullptr;
- }
-
- static const TestResult* GetTestResult(
- const TestInfo* test_info) {
- return test_info->result();
- }
-};
-
-// Tests TestInfo::test_case_name() and TestInfo::name().
-TEST_F(TestInfoTest, Names) {
- const TestInfo* const test_info = GetTestInfo("Names");
-
- ASSERT_STREQ("TestInfoTest", test_info->test_case_name());
- ASSERT_STREQ("Names", test_info->name());
-}
-
-// Tests TestInfo::result().
-TEST_F(TestInfoTest, result) {
- const TestInfo* const test_info = GetTestInfo("result");
-
- // Initially, there is no TestPartResult for this test.
- ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
-
- // After the previous assertion, there is still none.
- ASSERT_EQ(0, GetTestResult(test_info)->total_part_count());
-}
-
-#define VERIFY_CODE_LOCATION \
- const int expected_line = __LINE__ - 1; \
- const TestInfo* const test_info = GetUnitTestImpl()->current_test_info(); \
- ASSERT_TRUE(test_info); \
- EXPECT_STREQ(__FILE__, test_info->file()); \
- EXPECT_EQ(expected_line, test_info->line())
-
-TEST(CodeLocationForTEST, Verify) {
- VERIFY_CODE_LOCATION;
-}
-
-class CodeLocationForTESTF : public Test {
-};
-
-TEST_F(CodeLocationForTESTF, Verify) {
- VERIFY_CODE_LOCATION;
-}
-
-class CodeLocationForTESTP : public TestWithParam<int> {
-};
-
-TEST_P(CodeLocationForTESTP, Verify) {
- VERIFY_CODE_LOCATION;
-}
-
-INSTANTIATE_TEST_SUITE_P(, CodeLocationForTESTP, Values(0));
-
-template <typename T>
-class CodeLocationForTYPEDTEST : public Test {
-};
-
-TYPED_TEST_SUITE(CodeLocationForTYPEDTEST, int);
-
-TYPED_TEST(CodeLocationForTYPEDTEST, Verify) {
- VERIFY_CODE_LOCATION;
-}
-
-template <typename T>
-class CodeLocationForTYPEDTESTP : public Test {
-};
-
-TYPED_TEST_SUITE_P(CodeLocationForTYPEDTESTP);
-
-TYPED_TEST_P(CodeLocationForTYPEDTESTP, Verify) {
- VERIFY_CODE_LOCATION;
-}
-
-REGISTER_TYPED_TEST_SUITE_P(CodeLocationForTYPEDTESTP, Verify);
-
-INSTANTIATE_TYPED_TEST_SUITE_P(My, CodeLocationForTYPEDTESTP, int);
-
-#undef VERIFY_CODE_LOCATION
-
-// Tests setting up and tearing down a test case.
-// Legacy API is deprecated but still available
-#ifndef REMOVE_LEGACY_TEST_CASEAPI
-class SetUpTestCaseTest : public Test {
- protected:
- // This will be called once before the first test in this test case
- // is run.
- static void SetUpTestCase() {
- printf("Setting up the test case . . .\n");
-
- // Initializes some shared resource. In this simple example, we
- // just create a C string. More complex stuff can be done if
- // desired.
- shared_resource_ = "123";
-
- // Increments the number of test cases that have been set up.
- counter_++;
-
- // SetUpTestCase() should be called only once.
- EXPECT_EQ(1, counter_);
- }
-
- // This will be called once after the last test in this test case is
- // run.
- static void TearDownTestCase() {
- printf("Tearing down the test case . . .\n");
-
- // Decrements the number of test cases that have been set up.
- counter_--;
-
- // TearDownTestCase() should be called only once.
- EXPECT_EQ(0, counter_);
-
- // Cleans up the shared resource.
- shared_resource_ = nullptr;
- }
-
- // This will be called before each test in this test case.
- void SetUp() override {
- // SetUpTestCase() should be called only once, so counter_ should
- // always be 1.
- EXPECT_EQ(1, counter_);
- }
-
- // Number of test cases that have been set up.
- static int counter_;
-
- // Some resource to be shared by all tests in this test case.
- static const char* shared_resource_;
-};
-
-int SetUpTestCaseTest::counter_ = 0;
-const char* SetUpTestCaseTest::shared_resource_ = nullptr;
-
-// A test that uses the shared resource.
-TEST_F(SetUpTestCaseTest, Test1) { EXPECT_STRNE(nullptr, shared_resource_); }
-
-// Another test that uses the shared resource.
-TEST_F(SetUpTestCaseTest, Test2) {
- EXPECT_STREQ("123", shared_resource_);
-}
-#endif // REMOVE_LEGACY_TEST_CASEAPI
-
-// Tests SetupTestSuite/TearDown TestSuite
-class SetUpTestSuiteTest : public Test {
- protected:
- // This will be called once before the first test in this test case
- // is run.
- static void SetUpTestSuite() {
- printf("Setting up the test suite . . .\n");
-
- // Initializes some shared resource. In this simple example, we
- // just create a C string. More complex stuff can be done if
- // desired.
- shared_resource_ = "123";
-
- // Increments the number of test cases that have been set up.
- counter_++;
-
- // SetUpTestSuite() should be called only once.
- EXPECT_EQ(1, counter_);
- }
-
- // This will be called once after the last test in this test case is
- // run.
- static void TearDownTestSuite() {
- printf("Tearing down the test suite . . .\n");
-
- // Decrements the number of test suites that have been set up.
- counter_--;
-
- // TearDownTestSuite() should be called only once.
- EXPECT_EQ(0, counter_);
-
- // Cleans up the shared resource.
- shared_resource_ = nullptr;
- }
-
- // This will be called before each test in this test case.
- void SetUp() override {
- // SetUpTestSuite() should be called only once, so counter_ should
- // always be 1.
- EXPECT_EQ(1, counter_);
- }
-
- // Number of test suites that have been set up.
- static int counter_;
-
- // Some resource to be shared by all tests in this test case.
- static const char* shared_resource_;
-};
-
-int SetUpTestSuiteTest::counter_ = 0;
-const char* SetUpTestSuiteTest::shared_resource_ = nullptr;
-
-// A test that uses the shared resource.
-TEST_F(SetUpTestSuiteTest, TestSetupTestSuite1) {
- EXPECT_STRNE(nullptr, shared_resource_);
-}
-
-// Another test that uses the shared resource.
-TEST_F(SetUpTestSuiteTest, TestSetupTestSuite2) {
- EXPECT_STREQ("123", shared_resource_);
-}
-
-// The ParseFlagsTest test case tests ParseGoogleTestFlagsOnly.
-
-// The Flags struct stores a copy of all Google Test flags.
-struct Flags {
- // Constructs a Flags struct where each flag has its default value.
- Flags() : also_run_disabled_tests(false),
- break_on_failure(false),
- catch_exceptions(false),
- death_test_use_fork(false),
- filter(""),
- list_tests(false),
- output(""),
- print_time(true),
- random_seed(0),
- repeat(1),
- shuffle(false),
- stack_trace_depth(kMaxStackTraceDepth),
- stream_result_to(""),
- throw_on_failure(false) {}
-
- // Factory methods.
-
- // Creates a Flags struct where the gtest_also_run_disabled_tests flag has
- // the given value.
- static Flags AlsoRunDisabledTests(bool also_run_disabled_tests) {
- Flags flags;
- flags.also_run_disabled_tests = also_run_disabled_tests;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_break_on_failure flag has
- // the given value.
- static Flags BreakOnFailure(bool break_on_failure) {
- Flags flags;
- flags.break_on_failure = break_on_failure;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_catch_exceptions flag has
- // the given value.
- static Flags CatchExceptions(bool catch_exceptions) {
- Flags flags;
- flags.catch_exceptions = catch_exceptions;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_death_test_use_fork flag has
- // the given value.
- static Flags DeathTestUseFork(bool death_test_use_fork) {
- Flags flags;
- flags.death_test_use_fork = death_test_use_fork;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_filter flag has the given
- // value.
- static Flags Filter(const char* filter) {
- Flags flags;
- flags.filter = filter;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_list_tests flag has the
- // given value.
- static Flags ListTests(bool list_tests) {
- Flags flags;
- flags.list_tests = list_tests;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_output flag has the given
- // value.
- static Flags Output(const char* output) {
- Flags flags;
- flags.output = output;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_print_time flag has the given
- // value.
- static Flags PrintTime(bool print_time) {
- Flags flags;
- flags.print_time = print_time;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_random_seed flag has the given
- // value.
- static Flags RandomSeed(Int32 random_seed) {
- Flags flags;
- flags.random_seed = random_seed;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_repeat flag has the given
- // value.
- static Flags Repeat(Int32 repeat) {
- Flags flags;
- flags.repeat = repeat;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_shuffle flag has the given
- // value.
- static Flags Shuffle(bool shuffle) {
- Flags flags;
- flags.shuffle = shuffle;
- return flags;
- }
-
- // Creates a Flags struct where the GTEST_FLAG(stack_trace_depth) flag has
- // the given value.
- static Flags StackTraceDepth(Int32 stack_trace_depth) {
- Flags flags;
- flags.stack_trace_depth = stack_trace_depth;
- return flags;
- }
-
- // Creates a Flags struct where the GTEST_FLAG(stream_result_to) flag has
- // the given value.
- static Flags StreamResultTo(const char* stream_result_to) {
- Flags flags;
- flags.stream_result_to = stream_result_to;
- return flags;
- }
-
- // Creates a Flags struct where the gtest_throw_on_failure flag has
- // the given value.
- static Flags ThrowOnFailure(bool throw_on_failure) {
- Flags flags;
- flags.throw_on_failure = throw_on_failure;
- return flags;
- }
-
- // These fields store the flag values.
- bool also_run_disabled_tests;
- bool break_on_failure;
- bool catch_exceptions;
- bool death_test_use_fork;
- const char* filter;
- bool list_tests;
- const char* output;
- bool print_time;
- Int32 random_seed;
- Int32 repeat;
- bool shuffle;
- Int32 stack_trace_depth;
- const char* stream_result_to;
- bool throw_on_failure;
-};
-
-// Fixture for testing ParseGoogleTestFlagsOnly().
-class ParseFlagsTest : public Test {
- protected:
- // Clears the flags before each test.
- void SetUp() override {
- GTEST_FLAG(also_run_disabled_tests) = false;
- GTEST_FLAG(break_on_failure) = false;
- GTEST_FLAG(catch_exceptions) = false;
- GTEST_FLAG(death_test_use_fork) = false;
- GTEST_FLAG(filter) = "";
- GTEST_FLAG(list_tests) = false;
- GTEST_FLAG(output) = "";
- GTEST_FLAG(print_time) = true;
- GTEST_FLAG(random_seed) = 0;
- GTEST_FLAG(repeat) = 1;
- GTEST_FLAG(shuffle) = false;
- GTEST_FLAG(stack_trace_depth) = kMaxStackTraceDepth;
- GTEST_FLAG(stream_result_to) = "";
- GTEST_FLAG(throw_on_failure) = false;
- }
-
- // Asserts that two narrow or wide string arrays are equal.
- template <typename CharType>
- static void AssertStringArrayEq(int size1, CharType** array1, int size2,
- CharType** array2) {
- ASSERT_EQ(size1, size2) << " Array sizes different.";
-
- for (int i = 0; i != size1; i++) {
- ASSERT_STREQ(array1[i], array2[i]) << " where i == " << i;
- }
- }
-
- // Verifies that the flag values match the expected values.
- static void CheckFlags(const Flags& expected) {
- EXPECT_EQ(expected.also_run_disabled_tests,
- GTEST_FLAG(also_run_disabled_tests));
- EXPECT_EQ(expected.break_on_failure, GTEST_FLAG(break_on_failure));
- EXPECT_EQ(expected.catch_exceptions, GTEST_FLAG(catch_exceptions));
- EXPECT_EQ(expected.death_test_use_fork, GTEST_FLAG(death_test_use_fork));
- EXPECT_STREQ(expected.filter, GTEST_FLAG(filter).c_str());
- EXPECT_EQ(expected.list_tests, GTEST_FLAG(list_tests));
- EXPECT_STREQ(expected.output, GTEST_FLAG(output).c_str());
- EXPECT_EQ(expected.print_time, GTEST_FLAG(print_time));
- EXPECT_EQ(expected.random_seed, GTEST_FLAG(random_seed));
- EXPECT_EQ(expected.repeat, GTEST_FLAG(repeat));
- EXPECT_EQ(expected.shuffle, GTEST_FLAG(shuffle));
- EXPECT_EQ(expected.stack_trace_depth, GTEST_FLAG(stack_trace_depth));
- EXPECT_STREQ(expected.stream_result_to,
- GTEST_FLAG(stream_result_to).c_str());
- EXPECT_EQ(expected.throw_on_failure, GTEST_FLAG(throw_on_failure));
- }
-
- // Parses a command line (specified by argc1 and argv1), then
- // verifies that the flag values are expected and that the
- // recognized flags are removed from the command line.
- template <typename CharType>
- static void TestParsingFlags(int argc1, const CharType** argv1,
- int argc2, const CharType** argv2,
- const Flags& expected, bool should_print_help) {
- const bool saved_help_flag = ::testing::internal::g_help_flag;
- ::testing::internal::g_help_flag = false;
-
-# if GTEST_HAS_STREAM_REDIRECTION
- CaptureStdout();
-# endif
-
- // Parses the command line.
- internal::ParseGoogleTestFlagsOnly(&argc1, const_cast<CharType**>(argv1));
-
-# if GTEST_HAS_STREAM_REDIRECTION
- const std::string captured_stdout = GetCapturedStdout();
-# endif
-
- // Verifies the flag values.
- CheckFlags(expected);
-
- // Verifies that the recognized flags are removed from the command
- // line.
- AssertStringArrayEq(argc1 + 1, argv1, argc2 + 1, argv2);
-
- // ParseGoogleTestFlagsOnly should neither set g_help_flag nor print the
- // help message for the flags it recognizes.
- EXPECT_EQ(should_print_help, ::testing::internal::g_help_flag);
-
-# if GTEST_HAS_STREAM_REDIRECTION
- const char* const expected_help_fragment =
- "This program contains tests written using";
- if (should_print_help) {
- EXPECT_PRED_FORMAT2(IsSubstring, expected_help_fragment, captured_stdout);
- } else {
- EXPECT_PRED_FORMAT2(IsNotSubstring,
- expected_help_fragment, captured_stdout);
- }
-# endif // GTEST_HAS_STREAM_REDIRECTION
-
- ::testing::internal::g_help_flag = saved_help_flag;
- }
-
- // This macro wraps TestParsingFlags s.t. the user doesn't need
- // to specify the array sizes.
-
-# define GTEST_TEST_PARSING_FLAGS_(argv1, argv2, expected, should_print_help) \
- TestParsingFlags(sizeof(argv1)/sizeof(*argv1) - 1, argv1, \
- sizeof(argv2)/sizeof(*argv2) - 1, argv2, \
- expected, should_print_help)
-};
-
-// Tests parsing an empty command line.
-TEST_F(ParseFlagsTest, Empty) {
- const char* argv[] = {nullptr};
-
- const char* argv2[] = {nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
-}
-
-// Tests parsing a command line that has no flag.
-TEST_F(ParseFlagsTest, NoFlag) {
- const char* argv[] = {"foo.exe", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
-}
-
-// Tests parsing a bad --gtest_filter flag.
-TEST_F(ParseFlagsTest, FilterBad) {
- const char* argv[] = {"foo.exe", "--gtest_filter", nullptr};
-
- const char* argv2[] = {"foo.exe", "--gtest_filter", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), true);
-}
-
-// Tests parsing an empty --gtest_filter flag.
-TEST_F(ParseFlagsTest, FilterEmpty) {
- const char* argv[] = {"foo.exe", "--gtest_filter=", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter(""), false);
-}
-
-// Tests parsing a non-empty --gtest_filter flag.
-TEST_F(ParseFlagsTest, FilterNonEmpty) {
- const char* argv[] = {"foo.exe", "--gtest_filter=abc", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
-}
-
-// Tests parsing --gtest_break_on_failure.
-TEST_F(ParseFlagsTest, BreakOnFailureWithoutValue) {
- const char* argv[] = {"foo.exe", "--gtest_break_on_failure", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
-}
-
-// Tests parsing --gtest_break_on_failure=0.
-TEST_F(ParseFlagsTest, BreakOnFailureFalse_0) {
- const char* argv[] = {"foo.exe", "--gtest_break_on_failure=0", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
-}
-
-// Tests parsing --gtest_break_on_failure=f.
-TEST_F(ParseFlagsTest, BreakOnFailureFalse_f) {
- const char* argv[] = {"foo.exe", "--gtest_break_on_failure=f", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
-}
-
-// Tests parsing --gtest_break_on_failure=F.
-TEST_F(ParseFlagsTest, BreakOnFailureFalse_F) {
- const char* argv[] = {"foo.exe", "--gtest_break_on_failure=F", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(false), false);
-}
-
-// Tests parsing a --gtest_break_on_failure flag that has a "true"
-// definition.
-TEST_F(ParseFlagsTest, BreakOnFailureTrue) {
- const char* argv[] = {"foo.exe", "--gtest_break_on_failure=1", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::BreakOnFailure(true), false);
-}
-
-// Tests parsing --gtest_catch_exceptions.
-TEST_F(ParseFlagsTest, CatchExceptions) {
- const char* argv[] = {"foo.exe", "--gtest_catch_exceptions", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::CatchExceptions(true), false);
-}
-
-// Tests parsing --gtest_death_test_use_fork.
-TEST_F(ParseFlagsTest, DeathTestUseFork) {
- const char* argv[] = {"foo.exe", "--gtest_death_test_use_fork", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::DeathTestUseFork(true), false);
-}
-
-// Tests having the same flag twice with different values. The
-// expected behavior is that the one coming last takes precedence.
-TEST_F(ParseFlagsTest, DuplicatedFlags) {
- const char* argv[] = {"foo.exe", "--gtest_filter=a", "--gtest_filter=b",
- nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("b"), false);
-}
-
-// Tests having an unrecognized flag on the command line.
-TEST_F(ParseFlagsTest, UnrecognizedFlag) {
- const char* argv[] = {"foo.exe", "--gtest_break_on_failure",
- "bar", // Unrecognized by Google Test.
- "--gtest_filter=b", nullptr};
-
- const char* argv2[] = {"foo.exe", "bar", nullptr};
-
- Flags flags;
- flags.break_on_failure = true;
- flags.filter = "b";
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, flags, false);
-}
-
-// Tests having a --gtest_list_tests flag
-TEST_F(ParseFlagsTest, ListTestsFlag) {
- const char* argv[] = {"foo.exe", "--gtest_list_tests", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
-}
-
-// Tests having a --gtest_list_tests flag with a "true" value
-TEST_F(ParseFlagsTest, ListTestsTrue) {
- const char* argv[] = {"foo.exe", "--gtest_list_tests=1", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(true), false);
-}
-
-// Tests having a --gtest_list_tests flag with a "false" value
-TEST_F(ParseFlagsTest, ListTestsFalse) {
- const char* argv[] = {"foo.exe", "--gtest_list_tests=0", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
-}
-
-// Tests parsing --gtest_list_tests=f.
-TEST_F(ParseFlagsTest, ListTestsFalse_f) {
- const char* argv[] = {"foo.exe", "--gtest_list_tests=f", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
-}
-
-// Tests parsing --gtest_list_tests=F.
-TEST_F(ParseFlagsTest, ListTestsFalse_F) {
- const char* argv[] = {"foo.exe", "--gtest_list_tests=F", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ListTests(false), false);
-}
-
-// Tests parsing --gtest_output (invalid).
-TEST_F(ParseFlagsTest, OutputEmpty) {
- const char* argv[] = {"foo.exe", "--gtest_output", nullptr};
-
- const char* argv2[] = {"foo.exe", "--gtest_output", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), true);
-}
-
-// Tests parsing --gtest_output=xml
-TEST_F(ParseFlagsTest, OutputXml) {
- const char* argv[] = {"foo.exe", "--gtest_output=xml", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml"), false);
-}
-
-// Tests parsing --gtest_output=xml:file
-TEST_F(ParseFlagsTest, OutputXmlFile) {
- const char* argv[] = {"foo.exe", "--gtest_output=xml:file", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Output("xml:file"), false);
-}
-
-// Tests parsing --gtest_output=xml:directory/path/
-TEST_F(ParseFlagsTest, OutputXmlDirectory) {
- const char* argv[] = {"foo.exe", "--gtest_output=xml:directory/path/",
- nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2,
- Flags::Output("xml:directory/path/"), false);
-}
-
-// Tests having a --gtest_print_time flag
-TEST_F(ParseFlagsTest, PrintTimeFlag) {
- const char* argv[] = {"foo.exe", "--gtest_print_time", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
-}
-
-// Tests having a --gtest_print_time flag with a "true" value
-TEST_F(ParseFlagsTest, PrintTimeTrue) {
- const char* argv[] = {"foo.exe", "--gtest_print_time=1", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(true), false);
-}
-
-// Tests having a --gtest_print_time flag with a "false" value
-TEST_F(ParseFlagsTest, PrintTimeFalse) {
- const char* argv[] = {"foo.exe", "--gtest_print_time=0", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
-}
-
-// Tests parsing --gtest_print_time=f.
-TEST_F(ParseFlagsTest, PrintTimeFalse_f) {
- const char* argv[] = {"foo.exe", "--gtest_print_time=f", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
-}
-
-// Tests parsing --gtest_print_time=F.
-TEST_F(ParseFlagsTest, PrintTimeFalse_F) {
- const char* argv[] = {"foo.exe", "--gtest_print_time=F", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::PrintTime(false), false);
-}
-
-// Tests parsing --gtest_random_seed=number
-TEST_F(ParseFlagsTest, RandomSeed) {
- const char* argv[] = {"foo.exe", "--gtest_random_seed=1000", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::RandomSeed(1000), false);
-}
-
-// Tests parsing --gtest_repeat=number
-TEST_F(ParseFlagsTest, Repeat) {
- const char* argv[] = {"foo.exe", "--gtest_repeat=1000", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Repeat(1000), false);
-}
-
-// Tests having a --gtest_also_run_disabled_tests flag
-TEST_F(ParseFlagsTest, AlsoRunDisabledTestsFlag) {
- const char* argv[] = {"foo.exe", "--gtest_also_run_disabled_tests", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(true),
- false);
-}
-
-// Tests having a --gtest_also_run_disabled_tests flag with a "true" value
-TEST_F(ParseFlagsTest, AlsoRunDisabledTestsTrue) {
- const char* argv[] = {"foo.exe", "--gtest_also_run_disabled_tests=1",
- nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(true),
- false);
-}
-
-// Tests having a --gtest_also_run_disabled_tests flag with a "false" value
-TEST_F(ParseFlagsTest, AlsoRunDisabledTestsFalse) {
- const char* argv[] = {"foo.exe", "--gtest_also_run_disabled_tests=0",
- nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::AlsoRunDisabledTests(false),
- false);
-}
-
-// Tests parsing --gtest_shuffle.
-TEST_F(ParseFlagsTest, ShuffleWithoutValue) {
- const char* argv[] = {"foo.exe", "--gtest_shuffle", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
-}
-
-// Tests parsing --gtest_shuffle=0.
-TEST_F(ParseFlagsTest, ShuffleFalse_0) {
- const char* argv[] = {"foo.exe", "--gtest_shuffle=0", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(false), false);
-}
-
-// Tests parsing a --gtest_shuffle flag that has a "true" definition.
-TEST_F(ParseFlagsTest, ShuffleTrue) {
- const char* argv[] = {"foo.exe", "--gtest_shuffle=1", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Shuffle(true), false);
-}
-
-// Tests parsing --gtest_stack_trace_depth=number.
-TEST_F(ParseFlagsTest, StackTraceDepth) {
- const char* argv[] = {"foo.exe", "--gtest_stack_trace_depth=5", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::StackTraceDepth(5), false);
-}
-
-TEST_F(ParseFlagsTest, StreamResultTo) {
- const char* argv[] = {"foo.exe", "--gtest_stream_result_to=localhost:1234",
- nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(
- argv, argv2, Flags::StreamResultTo("localhost:1234"), false);
-}
-
-// Tests parsing --gtest_throw_on_failure.
-TEST_F(ParseFlagsTest, ThrowOnFailureWithoutValue) {
- const char* argv[] = {"foo.exe", "--gtest_throw_on_failure", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
-}
-
-// Tests parsing --gtest_throw_on_failure=0.
-TEST_F(ParseFlagsTest, ThrowOnFailureFalse_0) {
- const char* argv[] = {"foo.exe", "--gtest_throw_on_failure=0", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(false), false);
-}
-
-// Tests parsing a --gtest_throw_on_failure flag that has a "true"
-// definition.
-TEST_F(ParseFlagsTest, ThrowOnFailureTrue) {
- const char* argv[] = {"foo.exe", "--gtest_throw_on_failure=1", nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::ThrowOnFailure(true), false);
-}
-
-# if GTEST_OS_WINDOWS
-// Tests parsing wide strings.
-TEST_F(ParseFlagsTest, WideStrings) {
- const wchar_t* argv[] = {
- L"foo.exe",
- L"--gtest_filter=Foo*",
- L"--gtest_list_tests=1",
- L"--gtest_break_on_failure",
- L"--non_gtest_flag",
- NULL
- };
-
- const wchar_t* argv2[] = {
- L"foo.exe",
- L"--non_gtest_flag",
- NULL
- };
-
- Flags expected_flags;
- expected_flags.break_on_failure = true;
- expected_flags.filter = "Foo*";
- expected_flags.list_tests = true;
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
-}
-# endif // GTEST_OS_WINDOWS
-
-#if GTEST_USE_OWN_FLAGFILE_FLAG_
-class FlagfileTest : public ParseFlagsTest {
- public:
- virtual void SetUp() {
- ParseFlagsTest::SetUp();
-
- testdata_path_.Set(internal::FilePath(
- testing::TempDir() + internal::GetCurrentExecutableName().string() +
- "_flagfile_test"));
- testing::internal::posix::RmDir(testdata_path_.c_str());
- EXPECT_TRUE(testdata_path_.CreateFolder());
- }
-
- virtual void TearDown() {
- testing::internal::posix::RmDir(testdata_path_.c_str());
- ParseFlagsTest::TearDown();
- }
-
- internal::FilePath CreateFlagfile(const char* contents) {
- internal::FilePath file_path(internal::FilePath::GenerateUniqueFileName(
- testdata_path_, internal::FilePath("unique"), "txt"));
- FILE* f = testing::internal::posix::FOpen(file_path.c_str(), "w");
- fprintf(f, "%s", contents);
- fclose(f);
- return file_path;
- }
-
- private:
- internal::FilePath testdata_path_;
-};
-
-// Tests an empty flagfile.
-TEST_F(FlagfileTest, Empty) {
- internal::FilePath flagfile_path(CreateFlagfile(""));
- std::string flagfile_flag =
- std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
-
- const char* argv[] = {"foo.exe", flagfile_flag.c_str(), nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags(), false);
-}
-
-// Tests passing a non-empty --gtest_filter flag via --gtest_flagfile.
-TEST_F(FlagfileTest, FilterNonEmpty) {
- internal::FilePath flagfile_path(CreateFlagfile(
- "--" GTEST_FLAG_PREFIX_ "filter=abc"));
- std::string flagfile_flag =
- std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
-
- const char* argv[] = {"foo.exe", flagfile_flag.c_str(), nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, Flags::Filter("abc"), false);
-}
-
-// Tests passing several flags via --gtest_flagfile.
-TEST_F(FlagfileTest, SeveralFlags) {
- internal::FilePath flagfile_path(CreateFlagfile(
- "--" GTEST_FLAG_PREFIX_ "filter=abc\n"
- "--" GTEST_FLAG_PREFIX_ "break_on_failure\n"
- "--" GTEST_FLAG_PREFIX_ "list_tests"));
- std::string flagfile_flag =
- std::string("--" GTEST_FLAG_PREFIX_ "flagfile=") + flagfile_path.c_str();
-
- const char* argv[] = {"foo.exe", flagfile_flag.c_str(), nullptr};
-
- const char* argv2[] = {"foo.exe", nullptr};
-
- Flags expected_flags;
- expected_flags.break_on_failure = true;
- expected_flags.filter = "abc";
- expected_flags.list_tests = true;
-
- GTEST_TEST_PARSING_FLAGS_(argv, argv2, expected_flags, false);
-}
-#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
-
-// Tests current_test_info() in UnitTest.
-class CurrentTestInfoTest : public Test {
- protected:
- // Tests that current_test_info() returns NULL before the first test in
- // the test case is run.
- static void SetUpTestSuite() {
- // There should be no tests running at this point.
- const TestInfo* test_info =
- UnitTest::GetInstance()->current_test_info();
- EXPECT_TRUE(test_info == nullptr)
- << "There should be no tests running at this point.";
- }
-
- // Tests that current_test_info() returns NULL after the last test in
- // the test case has run.
- static void TearDownTestSuite() {
- const TestInfo* test_info =
- UnitTest::GetInstance()->current_test_info();
- EXPECT_TRUE(test_info == nullptr)
- << "There should be no tests running at this point.";
- }
-};
-
-// Tests that current_test_info() returns TestInfo for currently running
-// test by checking the expected test name against the actual one.
-TEST_F(CurrentTestInfoTest, WorksForFirstTestInATestSuite) {
- const TestInfo* test_info =
- UnitTest::GetInstance()->current_test_info();
- ASSERT_TRUE(nullptr != test_info)
- << "There is a test running so we should have a valid TestInfo.";
- EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
- << "Expected the name of the currently running test case.";
- EXPECT_STREQ("WorksForFirstTestInATestSuite", test_info->name())
- << "Expected the name of the currently running test.";
-}
-
-// Tests that current_test_info() returns TestInfo for currently running
-// test by checking the expected test name against the actual one. We
-// use this test to see that the TestInfo object actually changed from
-// the previous invocation.
-TEST_F(CurrentTestInfoTest, WorksForSecondTestInATestSuite) {
- const TestInfo* test_info =
- UnitTest::GetInstance()->current_test_info();
- ASSERT_TRUE(nullptr != test_info)
- << "There is a test running so we should have a valid TestInfo.";
- EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
- << "Expected the name of the currently running test case.";
- EXPECT_STREQ("WorksForSecondTestInATestSuite", test_info->name())
- << "Expected the name of the currently running test.";
-}
-
-} // namespace testing
-
-
-// These two lines test that we can define tests in a namespace that
-// has the name "testing" and is nested in another namespace.
-namespace my_namespace {
-namespace testing {
-
-// Makes sure that TEST knows to use ::testing::Test instead of
-// ::my_namespace::testing::Test.
-class Test {};
-
-// Makes sure that an assertion knows to use ::testing::Message instead of
-// ::my_namespace::testing::Message.
-class Message {};
-
-// Makes sure that an assertion knows to use
-// ::testing::AssertionResult instead of
-// ::my_namespace::testing::AssertionResult.
-class AssertionResult {};
-
-// Tests that an assertion that should succeed works as expected.
-TEST(NestedTestingNamespaceTest, Success) {
- EXPECT_EQ(1, 1) << "This shouldn't fail.";
-}
-
-// Tests that an assertion that should fail works as expected.
-TEST(NestedTestingNamespaceTest, Failure) {
- EXPECT_FATAL_FAILURE(FAIL() << "This failure is expected.",
- "This failure is expected.");
-}
-
-} // namespace testing
-} // namespace my_namespace
-
-// Tests that one can call superclass SetUp and TearDown methods--
-// that is, that they are not private.
-// No tests are based on this fixture; the test "passes" if it compiles
-// successfully.
-class ProtectedFixtureMethodsTest : public Test {
- protected:
- void SetUp() override { Test::SetUp(); }
- void TearDown() override { Test::TearDown(); }
-};
-
-// StreamingAssertionsTest tests the streaming versions of a representative
-// sample of assertions.
-TEST(StreamingAssertionsTest, Unconditional) {
- SUCCEED() << "expected success";
- EXPECT_NONFATAL_FAILURE(ADD_FAILURE() << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(FAIL() << "expected failure",
- "expected failure");
-}
-
-#ifdef __BORLANDC__
-// Silences warnings: "Condition is always true", "Unreachable code"
-# pragma option push -w-ccc -w-rch
-#endif
-
-TEST(StreamingAssertionsTest, Truth) {
- EXPECT_TRUE(true) << "unexpected failure";
- ASSERT_TRUE(true) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_TRUE(false) << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_TRUE(false) << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, Truth2) {
- EXPECT_FALSE(false) << "unexpected failure";
- ASSERT_FALSE(false) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(true) << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_FALSE(true) << "expected failure",
- "expected failure");
-}
-
-#ifdef __BORLANDC__
-// Restores warnings after previous "#pragma option push" suppressed them
-# pragma option pop
-#endif
-
-TEST(StreamingAssertionsTest, IntegerEquals) {
- EXPECT_EQ(1, 1) << "unexpected failure";
- ASSERT_EQ(1, 1) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_EQ(1, 2) << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_EQ(1, 2) << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, IntegerLessThan) {
- EXPECT_LT(1, 2) << "unexpected failure";
- ASSERT_LT(1, 2) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_LT(2, 1) << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_LT(2, 1) << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, StringsEqual) {
- EXPECT_STREQ("foo", "foo") << "unexpected failure";
- ASSERT_STREQ("foo", "foo") << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_STREQ("foo", "bar") << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_STREQ("foo", "bar") << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, StringsNotEqual) {
- EXPECT_STRNE("foo", "bar") << "unexpected failure";
- ASSERT_STRNE("foo", "bar") << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_STRNE("foo", "foo") << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_STRNE("foo", "foo") << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, StringsEqualIgnoringCase) {
- EXPECT_STRCASEEQ("foo", "FOO") << "unexpected failure";
- ASSERT_STRCASEEQ("foo", "FOO") << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_STRCASEEQ("foo", "bar") << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_STRCASEEQ("foo", "bar") << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, StringNotEqualIgnoringCase) {
- EXPECT_STRCASENE("foo", "bar") << "unexpected failure";
- ASSERT_STRCASENE("foo", "bar") << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_STRCASENE("foo", "FOO") << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_STRCASENE("bar", "BAR") << "expected failure",
- "expected failure");
-}
-
-TEST(StreamingAssertionsTest, FloatingPointEquals) {
- EXPECT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
- ASSERT_FLOAT_EQ(1.0, 1.0) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_FLOAT_EQ(0.0, 1.0) << "expected failure",
- "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_FLOAT_EQ(0.0, 1.0) << "expected failure",
- "expected failure");
-}
-
-#if GTEST_HAS_EXCEPTIONS
-
-TEST(StreamingAssertionsTest, Throw) {
- EXPECT_THROW(ThrowAnInteger(), int) << "unexpected failure";
- ASSERT_THROW(ThrowAnInteger(), int) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_THROW(ThrowAnInteger(), bool) <<
- "expected failure", "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_THROW(ThrowAnInteger(), bool) <<
- "expected failure", "expected failure");
-}
-
-TEST(StreamingAssertionsTest, NoThrow) {
- EXPECT_NO_THROW(ThrowNothing()) << "unexpected failure";
- ASSERT_NO_THROW(ThrowNothing()) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_NO_THROW(ThrowAnInteger()) <<
- "expected failure", "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_NO_THROW(ThrowAnInteger()) <<
- "expected failure", "expected failure");
-}
-
-TEST(StreamingAssertionsTest, AnyThrow) {
- EXPECT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
- ASSERT_ANY_THROW(ThrowAnInteger()) << "unexpected failure";
- EXPECT_NONFATAL_FAILURE(EXPECT_ANY_THROW(ThrowNothing()) <<
- "expected failure", "expected failure");
- EXPECT_FATAL_FAILURE(ASSERT_ANY_THROW(ThrowNothing()) <<
- "expected failure", "expected failure");
-}
-
-#endif // GTEST_HAS_EXCEPTIONS
-
-// Tests that Google Test correctly decides whether to use colors in the output.
-
-TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsYes) {
- GTEST_FLAG(color) = "yes";
-
- SetEnv("TERM", "xterm"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
- EXPECT_TRUE(ShouldUseColor(false)); // Stdout is not a TTY.
-
- SetEnv("TERM", "dumb"); // TERM doesn't support colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
- EXPECT_TRUE(ShouldUseColor(false)); // Stdout is not a TTY.
-}
-
-TEST(ColoredOutputTest, UsesColorsWhenGTestColorFlagIsAliasOfYes) {
- SetEnv("TERM", "dumb"); // TERM doesn't support colors.
-
- GTEST_FLAG(color) = "True";
- EXPECT_TRUE(ShouldUseColor(false)); // Stdout is not a TTY.
-
- GTEST_FLAG(color) = "t";
- EXPECT_TRUE(ShouldUseColor(false)); // Stdout is not a TTY.
-
- GTEST_FLAG(color) = "1";
- EXPECT_TRUE(ShouldUseColor(false)); // Stdout is not a TTY.
-}
-
-TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsNo) {
- GTEST_FLAG(color) = "no";
-
- SetEnv("TERM", "xterm"); // TERM supports colors.
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
- EXPECT_FALSE(ShouldUseColor(false)); // Stdout is not a TTY.
-
- SetEnv("TERM", "dumb"); // TERM doesn't support colors.
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
- EXPECT_FALSE(ShouldUseColor(false)); // Stdout is not a TTY.
-}
-
-TEST(ColoredOutputTest, UsesNoColorWhenGTestColorFlagIsInvalid) {
- SetEnv("TERM", "xterm"); // TERM supports colors.
-
- GTEST_FLAG(color) = "F";
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-
- GTEST_FLAG(color) = "0";
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-
- GTEST_FLAG(color) = "unknown";
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-}
-
-TEST(ColoredOutputTest, UsesColorsWhenStdoutIsTty) {
- GTEST_FLAG(color) = "auto";
-
- SetEnv("TERM", "xterm"); // TERM supports colors.
- EXPECT_FALSE(ShouldUseColor(false)); // Stdout is not a TTY.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-}
-
-TEST(ColoredOutputTest, UsesColorsWhenTermSupportsColors) {
- GTEST_FLAG(color) = "auto";
-
-#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW
- // On Windows, we ignore the TERM variable as it's usually not set.
-
- SetEnv("TERM", "dumb");
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "");
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "xterm");
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-#else
- // On non-Windows platforms, we rely on TERM to determine if the
- // terminal supports colors.
-
- SetEnv("TERM", "dumb"); // TERM doesn't support colors.
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "emacs"); // TERM doesn't support colors.
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "vt100"); // TERM doesn't support colors.
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "xterm-mono"); // TERM doesn't support colors.
- EXPECT_FALSE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "xterm"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "xterm-color"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "xterm-256color"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "screen"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "screen-256color"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "tmux"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "tmux-256color"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "rxvt-unicode"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "rxvt-unicode-256color"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "linux"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-
- SetEnv("TERM", "cygwin"); // TERM supports colors.
- EXPECT_TRUE(ShouldUseColor(true)); // Stdout is a TTY.
-#endif // GTEST_OS_WINDOWS
-}
-
-// Verifies that StaticAssertTypeEq works in a namespace scope.
-
-static bool dummy1 GTEST_ATTRIBUTE_UNUSED_ = StaticAssertTypeEq<bool, bool>();
-static bool dummy2 GTEST_ATTRIBUTE_UNUSED_ =
- StaticAssertTypeEq<const int, const int>();
-
-// Verifies that StaticAssertTypeEq works in a class.
-
-template <typename T>
-class StaticAssertTypeEqTestHelper {
- public:
- StaticAssertTypeEqTestHelper() { StaticAssertTypeEq<bool, T>(); }
-};
-
-TEST(StaticAssertTypeEqTest, WorksInClass) {
- StaticAssertTypeEqTestHelper<bool>();
-}
-
-// Verifies that StaticAssertTypeEq works inside a function.
-
-typedef int IntAlias;
-
-TEST(StaticAssertTypeEqTest, CompilesForEqualTypes) {
- StaticAssertTypeEq<int, IntAlias>();
- StaticAssertTypeEq<int*, IntAlias*>();
-}
-
-TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) {
- EXPECT_FALSE(HasNonfatalFailure());
-}
-
-static void FailFatally() { FAIL(); }
-
-TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsOnlyFatalFailure) {
- FailFatally();
- const bool has_nonfatal_failure = HasNonfatalFailure();
- ClearCurrentTestPartResults();
- EXPECT_FALSE(has_nonfatal_failure);
-}
-
-TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
- ADD_FAILURE();
- const bool has_nonfatal_failure = HasNonfatalFailure();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_nonfatal_failure);
-}
-
-TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
- FailFatally();
- ADD_FAILURE();
- const bool has_nonfatal_failure = HasNonfatalFailure();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_nonfatal_failure);
-}
-
-// A wrapper for calling HasNonfatalFailure outside of a test body.
-static bool HasNonfatalFailureHelper() {
- return testing::Test::HasNonfatalFailure();
-}
-
-TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody) {
- EXPECT_FALSE(HasNonfatalFailureHelper());
-}
-
-TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody2) {
- ADD_FAILURE();
- const bool has_nonfatal_failure = HasNonfatalFailureHelper();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_nonfatal_failure);
-}
-
-TEST(HasFailureTest, ReturnsFalseWhenThereIsNoFailure) {
- EXPECT_FALSE(HasFailure());
-}
-
-TEST(HasFailureTest, ReturnsTrueWhenThereIsFatalFailure) {
- FailFatally();
- const bool has_failure = HasFailure();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_failure);
-}
-
-TEST(HasFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
- ADD_FAILURE();
- const bool has_failure = HasFailure();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_failure);
-}
-
-TEST(HasFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
- FailFatally();
- ADD_FAILURE();
- const bool has_failure = HasFailure();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_failure);
-}
-
-// A wrapper for calling HasFailure outside of a test body.
-static bool HasFailureHelper() { return testing::Test::HasFailure(); }
-
-TEST(HasFailureTest, WorksOutsideOfTestBody) {
- EXPECT_FALSE(HasFailureHelper());
-}
-
-TEST(HasFailureTest, WorksOutsideOfTestBody2) {
- ADD_FAILURE();
- const bool has_failure = HasFailureHelper();
- ClearCurrentTestPartResults();
- EXPECT_TRUE(has_failure);
-}
-
-class TestListener : public EmptyTestEventListener {
- public:
- TestListener() : on_start_counter_(nullptr), is_destroyed_(nullptr) {}
- TestListener(int* on_start_counter, bool* is_destroyed)
- : on_start_counter_(on_start_counter),
- is_destroyed_(is_destroyed) {}
-
- ~TestListener() override {
- if (is_destroyed_)
- *is_destroyed_ = true;
- }
-
- protected:
- void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
- if (on_start_counter_ != nullptr) (*on_start_counter_)++;
- }
-
- private:
- int* on_start_counter_;
- bool* is_destroyed_;
-};
-
-// Tests the constructor.
-TEST(TestEventListenersTest, ConstructionWorks) {
- TestEventListeners listeners;
-
- EXPECT_TRUE(TestEventListenersAccessor::GetRepeater(&listeners) != nullptr);
- EXPECT_TRUE(listeners.default_result_printer() == nullptr);
- EXPECT_TRUE(listeners.default_xml_generator() == nullptr);
-}
-
-// Tests that the TestEventListeners destructor deletes all the listeners it
-// owns.
-TEST(TestEventListenersTest, DestructionWorks) {
- bool default_result_printer_is_destroyed = false;
- bool default_xml_printer_is_destroyed = false;
- bool extra_listener_is_destroyed = false;
- TestListener* default_result_printer =
- new TestListener(nullptr, &default_result_printer_is_destroyed);
- TestListener* default_xml_printer =
- new TestListener(nullptr, &default_xml_printer_is_destroyed);
- TestListener* extra_listener =
- new TestListener(nullptr, &extra_listener_is_destroyed);
-
- {
- TestEventListeners listeners;
- TestEventListenersAccessor::SetDefaultResultPrinter(&listeners,
- default_result_printer);
- TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners,
- default_xml_printer);
- listeners.Append(extra_listener);
- }
- EXPECT_TRUE(default_result_printer_is_destroyed);
- EXPECT_TRUE(default_xml_printer_is_destroyed);
- EXPECT_TRUE(extra_listener_is_destroyed);
-}
-
-// Tests that a listener Append'ed to a TestEventListeners list starts
-// receiving events.
-TEST(TestEventListenersTest, Append) {
- int on_start_counter = 0;
- bool is_destroyed = false;
- TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
- {
- TestEventListeners listeners;
- listeners.Append(listener);
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_EQ(1, on_start_counter);
- }
- EXPECT_TRUE(is_destroyed);
-}
-
-// Tests that listeners receive events in the order they were appended to
-// the list, except for *End requests, which must be received in the reverse
-// order.
-class SequenceTestingListener : public EmptyTestEventListener {
- public:
- SequenceTestingListener(std::vector<std::string>* vector, const char* id)
- : vector_(vector), id_(id) {}
-
- protected:
- void OnTestProgramStart(const UnitTest& /*unit_test*/) override {
- vector_->push_back(GetEventDescription("OnTestProgramStart"));
- }
-
- void OnTestProgramEnd(const UnitTest& /*unit_test*/) override {
- vector_->push_back(GetEventDescription("OnTestProgramEnd"));
- }
-
- void OnTestIterationStart(const UnitTest& /*unit_test*/,
- int /*iteration*/) override {
- vector_->push_back(GetEventDescription("OnTestIterationStart"));
- }
-
- void OnTestIterationEnd(const UnitTest& /*unit_test*/,
- int /*iteration*/) override {
- vector_->push_back(GetEventDescription("OnTestIterationEnd"));
- }
-
- private:
- std::string GetEventDescription(const char* method) {
- Message message;
- message << id_ << "." << method;
- return message.GetString();
- }
-
- std::vector<std::string>* vector_;
- const char* const id_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(SequenceTestingListener);
-};
-
-TEST(EventListenerTest, AppendKeepsOrder) {
- std::vector<std::string> vec;
- TestEventListeners listeners;
- listeners.Append(new SequenceTestingListener(&vec, "1st"));
- listeners.Append(new SequenceTestingListener(&vec, "2nd"));
- listeners.Append(new SequenceTestingListener(&vec, "3rd"));
-
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- ASSERT_EQ(3U, vec.size());
- EXPECT_STREQ("1st.OnTestProgramStart", vec[0].c_str());
- EXPECT_STREQ("2nd.OnTestProgramStart", vec[1].c_str());
- EXPECT_STREQ("3rd.OnTestProgramStart", vec[2].c_str());
-
- vec.clear();
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramEnd(
- *UnitTest::GetInstance());
- ASSERT_EQ(3U, vec.size());
- EXPECT_STREQ("3rd.OnTestProgramEnd", vec[0].c_str());
- EXPECT_STREQ("2nd.OnTestProgramEnd", vec[1].c_str());
- EXPECT_STREQ("1st.OnTestProgramEnd", vec[2].c_str());
-
- vec.clear();
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationStart(
- *UnitTest::GetInstance(), 0);
- ASSERT_EQ(3U, vec.size());
- EXPECT_STREQ("1st.OnTestIterationStart", vec[0].c_str());
- EXPECT_STREQ("2nd.OnTestIterationStart", vec[1].c_str());
- EXPECT_STREQ("3rd.OnTestIterationStart", vec[2].c_str());
-
- vec.clear();
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestIterationEnd(
- *UnitTest::GetInstance(), 0);
- ASSERT_EQ(3U, vec.size());
- EXPECT_STREQ("3rd.OnTestIterationEnd", vec[0].c_str());
- EXPECT_STREQ("2nd.OnTestIterationEnd", vec[1].c_str());
- EXPECT_STREQ("1st.OnTestIterationEnd", vec[2].c_str());
-}
-
-// Tests that a listener removed from a TestEventListeners list stops receiving
-// events and is not deleted when the list is destroyed.
-TEST(TestEventListenersTest, Release) {
- int on_start_counter = 0;
- bool is_destroyed = false;
- // Although Append passes the ownership of this object to the list,
- // the following calls release it, and we need to delete it before the
- // test ends.
- TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
- {
- TestEventListeners listeners;
- listeners.Append(listener);
- EXPECT_EQ(listener, listeners.Release(listener));
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_TRUE(listeners.Release(listener) == nullptr);
- }
- EXPECT_EQ(0, on_start_counter);
- EXPECT_FALSE(is_destroyed);
- delete listener;
-}
-
-// Tests that no events are forwarded when event forwarding is disabled.
-TEST(EventListenerTest, SuppressEventForwarding) {
- int on_start_counter = 0;
- TestListener* listener = new TestListener(&on_start_counter, nullptr);
-
- TestEventListeners listeners;
- listeners.Append(listener);
- ASSERT_TRUE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
- TestEventListenersAccessor::SuppressEventForwarding(&listeners);
- ASSERT_FALSE(TestEventListenersAccessor::EventForwardingEnabled(listeners));
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_EQ(0, on_start_counter);
-}
-
-// Tests that events generated by Google Test are not forwarded in
-// death test subprocesses.
-TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprecesses) {
- EXPECT_DEATH_IF_SUPPORTED({
- GTEST_CHECK_(TestEventListenersAccessor::EventForwardingEnabled(
- *GetUnitTestImpl()->listeners())) << "expected failure";},
- "expected failure");
-}
-
-// Tests that a listener installed via SetDefaultResultPrinter() starts
-// receiving events and is returned via default_result_printer() and that
-// the previous default_result_printer is removed from the list and deleted.
-TEST(EventListenerTest, default_result_printer) {
- int on_start_counter = 0;
- bool is_destroyed = false;
- TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
-
- TestEventListeners listeners;
- TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
-
- EXPECT_EQ(listener, listeners.default_result_printer());
-
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
-
- EXPECT_EQ(1, on_start_counter);
-
- // Replacing default_result_printer with something else should remove it
- // from the list and destroy it.
- TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, nullptr);
-
- EXPECT_TRUE(listeners.default_result_printer() == nullptr);
- EXPECT_TRUE(is_destroyed);
-
- // After broadcasting an event the counter is still the same, indicating
- // the listener is not in the list anymore.
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_EQ(1, on_start_counter);
-}
-
-// Tests that the default_result_printer listener stops receiving events
-// when removed via Release and that is not owned by the list anymore.
-TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
- int on_start_counter = 0;
- bool is_destroyed = false;
- // Although Append passes the ownership of this object to the list,
- // the following calls release it, and we need to delete it before the
- // test ends.
- TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
- {
- TestEventListeners listeners;
- TestEventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
-
- EXPECT_EQ(listener, listeners.Release(listener));
- EXPECT_TRUE(listeners.default_result_printer() == nullptr);
- EXPECT_FALSE(is_destroyed);
-
- // Broadcasting events now should not affect default_result_printer.
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_EQ(0, on_start_counter);
- }
- // Destroying the list should not affect the listener now, too.
- EXPECT_FALSE(is_destroyed);
- delete listener;
-}
-
-// Tests that a listener installed via SetDefaultXmlGenerator() starts
-// receiving events and is returned via default_xml_generator() and that
-// the previous default_xml_generator is removed from the list and deleted.
-TEST(EventListenerTest, default_xml_generator) {
- int on_start_counter = 0;
- bool is_destroyed = false;
- TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
-
- TestEventListeners listeners;
- TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
-
- EXPECT_EQ(listener, listeners.default_xml_generator());
-
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
-
- EXPECT_EQ(1, on_start_counter);
-
- // Replacing default_xml_generator with something else should remove it
- // from the list and destroy it.
- TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, nullptr);
-
- EXPECT_TRUE(listeners.default_xml_generator() == nullptr);
- EXPECT_TRUE(is_destroyed);
-
- // After broadcasting an event the counter is still the same, indicating
- // the listener is not in the list anymore.
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_EQ(1, on_start_counter);
-}
-
-// Tests that the default_xml_generator listener stops receiving events
-// when removed via Release and that is not owned by the list anymore.
-TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
- int on_start_counter = 0;
- bool is_destroyed = false;
- // Although Append passes the ownership of this object to the list,
- // the following calls release it, and we need to delete it before the
- // test ends.
- TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
- {
- TestEventListeners listeners;
- TestEventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
-
- EXPECT_EQ(listener, listeners.Release(listener));
- EXPECT_TRUE(listeners.default_xml_generator() == nullptr);
- EXPECT_FALSE(is_destroyed);
-
- // Broadcasting events now should not affect default_xml_generator.
- TestEventListenersAccessor::GetRepeater(&listeners)->OnTestProgramStart(
- *UnitTest::GetInstance());
- EXPECT_EQ(0, on_start_counter);
- }
- // Destroying the list should not affect the listener now, too.
- EXPECT_FALSE(is_destroyed);
- delete listener;
-}
-
-// Sanity tests to ensure that the alternative, verbose spellings of
-// some of the macros work. We don't test them thoroughly as that
-// would be quite involved. Since their implementations are
-// straightforward, and they are rarely used, we'll just rely on the
-// users to tell us when they are broken.
-GTEST_TEST(AlternativeNameTest, Works) { // GTEST_TEST is the same as TEST.
- GTEST_SUCCEED() << "OK"; // GTEST_SUCCEED is the same as SUCCEED.
-
- // GTEST_FAIL is the same as FAIL.
- EXPECT_FATAL_FAILURE(GTEST_FAIL() << "An expected failure",
- "An expected failure");
-
- // GTEST_ASSERT_XY is the same as ASSERT_XY.
-
- GTEST_ASSERT_EQ(0, 0);
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(0, 1) << "An expected failure",
- "An expected failure");
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_EQ(1, 0) << "An expected failure",
- "An expected failure");
-
- GTEST_ASSERT_NE(0, 1);
- GTEST_ASSERT_NE(1, 0);
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_NE(0, 0) << "An expected failure",
- "An expected failure");
-
- GTEST_ASSERT_LE(0, 0);
- GTEST_ASSERT_LE(0, 1);
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_LE(1, 0) << "An expected failure",
- "An expected failure");
-
- GTEST_ASSERT_LT(0, 1);
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(0, 0) << "An expected failure",
- "An expected failure");
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_LT(1, 0) << "An expected failure",
- "An expected failure");
-
- GTEST_ASSERT_GE(0, 0);
- GTEST_ASSERT_GE(1, 0);
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_GE(0, 1) << "An expected failure",
- "An expected failure");
-
- GTEST_ASSERT_GT(1, 0);
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(0, 1) << "An expected failure",
- "An expected failure");
- EXPECT_FATAL_FAILURE(GTEST_ASSERT_GT(1, 1) << "An expected failure",
- "An expected failure");
-}
-
-// Tests for internal utilities necessary for implementation of the universal
-// printing.
-
-class ConversionHelperBase {};
-class ConversionHelperDerived : public ConversionHelperBase {};
-
-// Tests that IsAProtocolMessage<T>::value is a compile-time constant.
-TEST(IsAProtocolMessageTest, ValueIsCompileTimeConstant) {
- GTEST_COMPILE_ASSERT_(IsAProtocolMessage<::proto2::Message>::value,
- const_true);
- GTEST_COMPILE_ASSERT_(!IsAProtocolMessage<int>::value, const_false);
-}
-
-// Tests that IsAProtocolMessage<T>::value is true when T is
-// proto2::Message or a sub-class of it.
-TEST(IsAProtocolMessageTest, ValueIsTrueWhenTypeIsAProtocolMessage) {
- EXPECT_TRUE(IsAProtocolMessage< ::proto2::Message>::value);
-}
-
-// Tests that IsAProtocolMessage<T>::value is false when T is neither
-// ::proto2::Message nor a sub-class of it.
-TEST(IsAProtocolMessageTest, ValueIsFalseWhenTypeIsNotAProtocolMessage) {
- EXPECT_FALSE(IsAProtocolMessage<int>::value);
- EXPECT_FALSE(IsAProtocolMessage<const ConversionHelperBase>::value);
-}
-
-// Tests GTEST_REMOVE_REFERENCE_AND_CONST_.
-
-template <typename T1, typename T2>
-void TestGTestRemoveReferenceAndConst() {
- static_assert(std::is_same<T1, GTEST_REMOVE_REFERENCE_AND_CONST_(T2)>::value,
- "GTEST_REMOVE_REFERENCE_AND_CONST_ failed.");
-}
-
-TEST(RemoveReferenceToConstTest, Works) {
- TestGTestRemoveReferenceAndConst<int, int>();
- TestGTestRemoveReferenceAndConst<double, double&>();
- TestGTestRemoveReferenceAndConst<char, const char>();
- TestGTestRemoveReferenceAndConst<char, const char&>();
- TestGTestRemoveReferenceAndConst<const char*, const char*>();
-}
-
-// Tests GTEST_REFERENCE_TO_CONST_.
-
-template <typename T1, typename T2>
-void TestGTestReferenceToConst() {
- static_assert(std::is_same<T1, GTEST_REFERENCE_TO_CONST_(T2)>::value,
- "GTEST_REFERENCE_TO_CONST_ failed.");
-}
-
-TEST(GTestReferenceToConstTest, Works) {
- TestGTestReferenceToConst<const char&, char>();
- TestGTestReferenceToConst<const int&, const int>();
- TestGTestReferenceToConst<const double&, double>();
- TestGTestReferenceToConst<const std::string&, const std::string&>();
-}
-
-
-// Tests IsContainerTest.
-
-class NonContainer {};
-
-TEST(IsContainerTestTest, WorksForNonContainer) {
- EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<int>(0)));
- EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<char[5]>(0)));
- EXPECT_EQ(sizeof(IsNotContainer), sizeof(IsContainerTest<NonContainer>(0)));
-}
-
-TEST(IsContainerTestTest, WorksForContainer) {
- EXPECT_EQ(sizeof(IsContainer),
- sizeof(IsContainerTest<std::vector<bool> >(0)));
- EXPECT_EQ(sizeof(IsContainer),
- sizeof(IsContainerTest<std::map<int, double> >(0)));
-}
-
-struct ConstOnlyContainerWithPointerIterator {
- using const_iterator = int*;
- const_iterator begin() const;
- const_iterator end() const;
-};
-
-struct ConstOnlyContainerWithClassIterator {
- struct const_iterator {
- const int& operator*() const;
- const_iterator& operator++(/* pre-increment */);
- };
- const_iterator begin() const;
- const_iterator end() const;
-};
-
-TEST(IsContainerTestTest, ConstOnlyContainer) {
- EXPECT_EQ(sizeof(IsContainer),
- sizeof(IsContainerTest<ConstOnlyContainerWithPointerIterator>(0)));
- EXPECT_EQ(sizeof(IsContainer),
- sizeof(IsContainerTest<ConstOnlyContainerWithClassIterator>(0)));
-}
-
-// Tests IsHashTable.
-struct AHashTable {
- typedef void hasher;
-};
-struct NotReallyAHashTable {
- typedef void hasher;
- typedef void reverse_iterator;
-};
-TEST(IsHashTable, Basic) {
- EXPECT_TRUE(testing::internal::IsHashTable<AHashTable>::value);
- EXPECT_FALSE(testing::internal::IsHashTable<NotReallyAHashTable>::value);
- EXPECT_FALSE(testing::internal::IsHashTable<std::vector<int>>::value);
- EXPECT_TRUE(testing::internal::IsHashTable<std::unordered_set<int>>::value);
-}
-
-// Tests ArrayEq().
-
-TEST(ArrayEqTest, WorksForDegeneratedArrays) {
- EXPECT_TRUE(ArrayEq(5, 5L));
- EXPECT_FALSE(ArrayEq('a', 0));
-}
-
-TEST(ArrayEqTest, WorksForOneDimensionalArrays) {
- // Note that a and b are distinct but compatible types.
- const int a[] = { 0, 1 };
- long b[] = { 0, 1 };
- EXPECT_TRUE(ArrayEq(a, b));
- EXPECT_TRUE(ArrayEq(a, 2, b));
-
- b[0] = 2;
- EXPECT_FALSE(ArrayEq(a, b));
- EXPECT_FALSE(ArrayEq(a, 1, b));
-}
-
-TEST(ArrayEqTest, WorksForTwoDimensionalArrays) {
- const char a[][3] = { "hi", "lo" };
- const char b[][3] = { "hi", "lo" };
- const char c[][3] = { "hi", "li" };
-
- EXPECT_TRUE(ArrayEq(a, b));
- EXPECT_TRUE(ArrayEq(a, 2, b));
-
- EXPECT_FALSE(ArrayEq(a, c));
- EXPECT_FALSE(ArrayEq(a, 2, c));
-}
-
-// Tests ArrayAwareFind().
-
-TEST(ArrayAwareFindTest, WorksForOneDimensionalArray) {
- const char a[] = "hello";
- EXPECT_EQ(a + 4, ArrayAwareFind(a, a + 5, 'o'));
- EXPECT_EQ(a + 5, ArrayAwareFind(a, a + 5, 'x'));
-}
-
-TEST(ArrayAwareFindTest, WorksForTwoDimensionalArray) {
- int a[][2] = { { 0, 1 }, { 2, 3 }, { 4, 5 } };
- const int b[2] = { 2, 3 };
- EXPECT_EQ(a + 1, ArrayAwareFind(a, a + 3, b));
-
- const int c[2] = { 6, 7 };
- EXPECT_EQ(a + 3, ArrayAwareFind(a, a + 3, c));
-}
-
-// Tests CopyArray().
-
-TEST(CopyArrayTest, WorksForDegeneratedArrays) {
- int n = 0;
- CopyArray('a', &n);
- EXPECT_EQ('a', n);
-}
-
-TEST(CopyArrayTest, WorksForOneDimensionalArrays) {
- const char a[3] = "hi";
- int b[3];
-#ifndef __BORLANDC__ // C++Builder cannot compile some array size deductions.
- CopyArray(a, &b);
- EXPECT_TRUE(ArrayEq(a, b));
-#endif
-
- int c[3];
- CopyArray(a, 3, c);
- EXPECT_TRUE(ArrayEq(a, c));
-}
-
-TEST(CopyArrayTest, WorksForTwoDimensionalArrays) {
- const int a[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };
- int b[2][3];
-#ifndef __BORLANDC__ // C++Builder cannot compile some array size deductions.
- CopyArray(a, &b);
- EXPECT_TRUE(ArrayEq(a, b));
-#endif
-
- int c[2][3];
- CopyArray(a, 2, c);
- EXPECT_TRUE(ArrayEq(a, c));
-}
-
-// Tests NativeArray.
-
-TEST(NativeArrayTest, ConstructorFromArrayWorks) {
- const int a[3] = { 0, 1, 2 };
- NativeArray<int> na(a, 3, RelationToSourceReference());
- EXPECT_EQ(3U, na.size());
- EXPECT_EQ(a, na.begin());
-}
-
-TEST(NativeArrayTest, CreatesAndDeletesCopyOfArrayWhenAskedTo) {
- typedef int Array[2];
- Array* a = new Array[1];
- (*a)[0] = 0;
- (*a)[1] = 1;
- NativeArray<int> na(*a, 2, RelationToSourceCopy());
- EXPECT_NE(*a, na.begin());
- delete[] a;
- EXPECT_EQ(0, na.begin()[0]);
- EXPECT_EQ(1, na.begin()[1]);
-
- // We rely on the heap checker to verify that na deletes the copy of
- // array.
-}
-
-TEST(NativeArrayTest, TypeMembersAreCorrect) {
- StaticAssertTypeEq<char, NativeArray<char>::value_type>();
- StaticAssertTypeEq<int[2], NativeArray<int[2]>::value_type>();
-
- StaticAssertTypeEq<const char*, NativeArray<char>::const_iterator>();
- StaticAssertTypeEq<const bool(*)[2], NativeArray<bool[2]>::const_iterator>();
-}
-
-TEST(NativeArrayTest, MethodsWork) {
- const int a[3] = { 0, 1, 2 };
- NativeArray<int> na(a, 3, RelationToSourceCopy());
- ASSERT_EQ(3U, na.size());
- EXPECT_EQ(3, na.end() - na.begin());
-
- NativeArray<int>::const_iterator it = na.begin();
- EXPECT_EQ(0, *it);
- ++it;
- EXPECT_EQ(1, *it);
- it++;
- EXPECT_EQ(2, *it);
- ++it;
- EXPECT_EQ(na.end(), it);
-
- EXPECT_TRUE(na == na);
-
- NativeArray<int> na2(a, 3, RelationToSourceReference());
- EXPECT_TRUE(na == na2);
-
- const int b1[3] = { 0, 1, 1 };
- const int b2[4] = { 0, 1, 2, 3 };
- EXPECT_FALSE(na == NativeArray<int>(b1, 3, RelationToSourceReference()));
- EXPECT_FALSE(na == NativeArray<int>(b2, 4, RelationToSourceCopy()));
-}
-
-TEST(NativeArrayTest, WorksForTwoDimensionalArray) {
- const char a[2][3] = { "hi", "lo" };
- NativeArray<char[3]> na(a, 2, RelationToSourceReference());
- ASSERT_EQ(2U, na.size());
- EXPECT_EQ(a, na.begin());
-}
-
-// IndexSequence
-TEST(IndexSequence, MakeIndexSequence) {
- using testing::internal::IndexSequence;
- using testing::internal::MakeIndexSequence;
- EXPECT_TRUE(
- (std::is_same<IndexSequence<>, MakeIndexSequence<0>::type>::value));
- EXPECT_TRUE(
- (std::is_same<IndexSequence<0>, MakeIndexSequence<1>::type>::value));
- EXPECT_TRUE(
- (std::is_same<IndexSequence<0, 1>, MakeIndexSequence<2>::type>::value));
- EXPECT_TRUE((
- std::is_same<IndexSequence<0, 1, 2>, MakeIndexSequence<3>::type>::value));
- EXPECT_TRUE(
- (std::is_base_of<IndexSequence<0, 1, 2>, MakeIndexSequence<3>>::value));
-}
-
-// ElemFromList
-TEST(ElemFromList, Basic) {
- using testing::internal::ElemFromList;
- using Idx = testing::internal::MakeIndexSequence<3>::type;
- EXPECT_TRUE((
- std::is_same<int, ElemFromList<0, Idx, int, double, char>::type>::value));
- EXPECT_TRUE(
- (std::is_same<double,
- ElemFromList<1, Idx, int, double, char>::type>::value));
- EXPECT_TRUE(
- (std::is_same<char,
- ElemFromList<2, Idx, int, double, char>::type>::value));
- EXPECT_TRUE(
- (std::is_same<
- char, ElemFromList<7, testing::internal::MakeIndexSequence<12>::type,
- int, int, int, int, int, int, int, char, int, int,
- int, int>::type>::value));
-}
-
-// FlatTuple
-TEST(FlatTuple, Basic) {
- using testing::internal::FlatTuple;
-
- FlatTuple<int, double, const char*> tuple = {};
- EXPECT_EQ(0, tuple.Get<0>());
- EXPECT_EQ(0.0, tuple.Get<1>());
- EXPECT_EQ(nullptr, tuple.Get<2>());
-
- tuple = FlatTuple<int, double, const char*>(7, 3.2, "Foo");
- EXPECT_EQ(7, tuple.Get<0>());
- EXPECT_EQ(3.2, tuple.Get<1>());
- EXPECT_EQ(std::string("Foo"), tuple.Get<2>());
-
- tuple.Get<1>() = 5.1;
- EXPECT_EQ(5.1, tuple.Get<1>());
-}
-
-TEST(FlatTuple, ManyTypes) {
- using testing::internal::FlatTuple;
-
- // Instantiate FlatTuple with 257 ints.
- // Tests show that we can do it with thousands of elements, but very long
- // compile times makes it unusuitable for this test.
-#define GTEST_FLAT_TUPLE_INT8 int, int, int, int, int, int, int, int,
-#define GTEST_FLAT_TUPLE_INT16 GTEST_FLAT_TUPLE_INT8 GTEST_FLAT_TUPLE_INT8
-#define GTEST_FLAT_TUPLE_INT32 GTEST_FLAT_TUPLE_INT16 GTEST_FLAT_TUPLE_INT16
-#define GTEST_FLAT_TUPLE_INT64 GTEST_FLAT_TUPLE_INT32 GTEST_FLAT_TUPLE_INT32
-#define GTEST_FLAT_TUPLE_INT128 GTEST_FLAT_TUPLE_INT64 GTEST_FLAT_TUPLE_INT64
-#define GTEST_FLAT_TUPLE_INT256 GTEST_FLAT_TUPLE_INT128 GTEST_FLAT_TUPLE_INT128
-
- // Let's make sure that we can have a very long list of types without blowing
- // up the template instantiation depth.
- FlatTuple<GTEST_FLAT_TUPLE_INT256 int> tuple;
-
- tuple.Get<0>() = 7;
- tuple.Get<99>() = 17;
- tuple.Get<256>() = 1000;
- EXPECT_EQ(7, tuple.Get<0>());
- EXPECT_EQ(17, tuple.Get<99>());
- EXPECT_EQ(1000, tuple.Get<256>());
-}
-
-// Tests SkipPrefix().
-
-TEST(SkipPrefixTest, SkipsWhenPrefixMatches) {
- const char* const str = "hello";
-
- const char* p = str;
- EXPECT_TRUE(SkipPrefix("", &p));
- EXPECT_EQ(str, p);
-
- p = str;
- EXPECT_TRUE(SkipPrefix("hell", &p));
- EXPECT_EQ(str + 4, p);
-}
-
-TEST(SkipPrefixTest, DoesNotSkipWhenPrefixDoesNotMatch) {
- const char* const str = "world";
-
- const char* p = str;
- EXPECT_FALSE(SkipPrefix("W", &p));
- EXPECT_EQ(str, p);
-
- p = str;
- EXPECT_FALSE(SkipPrefix("world!", &p));
- EXPECT_EQ(str, p);
-}
-
-// Tests ad_hoc_test_result().
-
-class AdHocTestResultTest : public testing::Test {
- protected:
- static void SetUpTestSuite() {
- FAIL() << "A failure happened inside SetUpTestSuite().";
- }
-};
-
-TEST_F(AdHocTestResultTest, AdHocTestResultForTestSuiteShowsFailure) {
- const testing::TestResult& test_result = testing::UnitTest::GetInstance()
- ->current_test_suite()
- ->ad_hoc_test_result();
- EXPECT_TRUE(test_result.Failed());
-}
-
-TEST_F(AdHocTestResultTest, AdHocTestResultTestForUnitTestDoesNotShowFailure) {
- const testing::TestResult& test_result =
- testing::UnitTest::GetInstance()->ad_hoc_test_result();
- EXPECT_FALSE(test_result.Failed());
-}
-
-class DynamicUnitTestFixture : public testing::Test {};
-
-class DynamicTest : public DynamicUnitTestFixture {
- void TestBody() override { EXPECT_TRUE(true); }
-};
-
-auto* dynamic_test = testing::RegisterTest(
- "DynamicUnitTestFixture", "DynamicTest", "TYPE", "VALUE", __FILE__,
- __LINE__, []() -> DynamicUnitTestFixture* { return new DynamicTest; });
-
-TEST(RegisterTest, WasRegistered) {
- auto* unittest = testing::UnitTest::GetInstance();
- for (int i = 0; i < unittest->total_test_suite_count(); ++i) {
- auto* tests = unittest->GetTestSuite(i);
- if (tests->name() != std::string("DynamicUnitTestFixture")) continue;
- for (int j = 0; j < tests->total_test_count(); ++j) {
- if (tests->GetTestInfo(j)->name() != std::string("DynamicTest")) continue;
- // Found it.
- EXPECT_STREQ(tests->GetTestInfo(j)->value_param(), "VALUE");
- EXPECT_STREQ(tests->GetTestInfo(j)->type_param(), "TYPE");
- return;
- }
- }
-
- FAIL() << "Didn't find the test!";
-}
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// gtest_xml_outfile1_test_ writes some xml via TestProperty used by
-// gtest_xml_outfiles_test.py
-
-#include "gtest/gtest.h"
-
-class PropertyOne : public testing::Test {
- protected:
- void SetUp() override { RecordProperty("SetUpProp", 1); }
- void TearDown() override { RecordProperty("TearDownProp", 1); }
-};
-
-TEST_F(PropertyOne, TestSomeProperties) {
- RecordProperty("TestSomeProperty", 1);
-}
+++ /dev/null
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// gtest_xml_outfile2_test_ writes some xml via TestProperty used by
-// gtest_xml_outfiles_test.py
-
-#include "gtest/gtest.h"
-
-class PropertyTwo : public testing::Test {
- protected:
- void SetUp() override { RecordProperty("SetUpProp", 2); }
- void TearDown() override { RecordProperty("TearDownProp", 2); }
-};
-
-TEST_F(PropertyTwo, TestSomeProperties) {
- RecordProperty("TestSomeProperty", 2);
-}
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2008, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for the gtest_xml_output module."""
-
-import os
-from xml.dom import minidom, Node
-import gtest_test_utils
-import gtest_xml_test_utils
-
-GTEST_OUTPUT_SUBDIR = "xml_outfiles"
-GTEST_OUTPUT_1_TEST = "gtest_xml_outfile1_test_"
-GTEST_OUTPUT_2_TEST = "gtest_xml_outfile2_test_"
-
-EXPECTED_XML_1 = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
- <testsuite name="PropertyOne" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="TestSomeProperties" status="run" result="completed" time="*" timestamp="*" classname="PropertyOne">
- <properties>
- <property name="SetUpProp" value="1"/>
- <property name="TestSomeProperty" value="1"/>
- <property name="TearDownProp" value="1"/>
- </properties>
- </testcase>
- </testsuite>
-</testsuites>
-"""
-
-EXPECTED_XML_2 = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests">
- <testsuite name="PropertyTwo" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="TestSomeProperties" status="run" result="completed" time="*" timestamp="*" classname="PropertyTwo">
- <properties>
- <property name="SetUpProp" value="2"/>
- <property name="TestSomeProperty" value="2"/>
- <property name="TearDownProp" value="2"/>
- </properties>
- </testcase>
- </testsuite>
-</testsuites>
-"""
-
-
-class GTestXMLOutFilesTest(gtest_xml_test_utils.GTestXMLTestCase):
- """Unit test for Google Test's XML output functionality."""
-
- def setUp(self):
- # We want the trailing '/' that the last "" provides in os.path.join, for
- # telling Google Test to create an output directory instead of a single file
- # for xml output.
- self.output_dir_ = os.path.join(gtest_test_utils.GetTempDir(),
- GTEST_OUTPUT_SUBDIR, "")
- self.DeleteFilesAndDir()
-
- def tearDown(self):
- self.DeleteFilesAndDir()
-
- def DeleteFilesAndDir(self):
- try:
- os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_1_TEST + ".xml"))
- except os.error:
- pass
- try:
- os.remove(os.path.join(self.output_dir_, GTEST_OUTPUT_2_TEST + ".xml"))
- except os.error:
- pass
- try:
- os.rmdir(self.output_dir_)
- except os.error:
- pass
-
- def testOutfile1(self):
- self._TestOutFile(GTEST_OUTPUT_1_TEST, EXPECTED_XML_1)
-
- def testOutfile2(self):
- self._TestOutFile(GTEST_OUTPUT_2_TEST, EXPECTED_XML_2)
-
- def _TestOutFile(self, test_name, expected_xml):
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(test_name)
- command = [gtest_prog_path, "--gtest_output=xml:%s" % self.output_dir_]
- p = gtest_test_utils.Subprocess(command,
- working_dir=gtest_test_utils.GetTempDir())
- self.assert_(p.exited)
- self.assertEquals(0, p.exit_code)
-
- output_file_name1 = test_name + ".xml"
- output_file1 = os.path.join(self.output_dir_, output_file_name1)
- output_file_name2 = 'lt-' + output_file_name1
- output_file2 = os.path.join(self.output_dir_, output_file_name2)
- self.assert_(os.path.isfile(output_file1) or os.path.isfile(output_file2),
- output_file1)
-
- expected = minidom.parseString(expected_xml)
- if os.path.isfile(output_file1):
- actual = minidom.parse(output_file1)
- else:
- actual = minidom.parse(output_file2)
- self.NormalizeXml(actual.documentElement)
- self.AssertEquivalentNodes(expected.documentElement,
- actual.documentElement)
- expected.unlink()
- actual.unlink()
-
-
-if __name__ == "__main__":
- os.environ["GTEST_STACK_TRACE_DEPTH"] = "0"
- gtest_test_utils.Main()
+++ /dev/null
-#!/usr/bin/env python
-#
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test for the gtest_xml_output module"""
-
-import datetime
-import errno
-import os
-import re
-import sys
-from xml.dom import minidom, Node
-
-import gtest_test_utils
-import gtest_xml_test_utils
-
-GTEST_FILTER_FLAG = '--gtest_filter'
-GTEST_LIST_TESTS_FLAG = '--gtest_list_tests'
-GTEST_OUTPUT_FLAG = '--gtest_output'
-GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml'
-GTEST_PROGRAM_NAME = 'gtest_xml_output_unittest_'
-
-# The flag indicating stacktraces are not supported
-NO_STACKTRACE_SUPPORT_FLAG = '--no_stacktrace_support'
-
-# The environment variables for test sharding.
-TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
-SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
-SHARD_STATUS_FILE_ENV_VAR = 'GTEST_SHARD_STATUS_FILE'
-
-SUPPORTS_STACK_TRACES = NO_STACKTRACE_SUPPORT_FLAG not in sys.argv
-
-if SUPPORTS_STACK_TRACES:
- STACK_TRACE_TEMPLATE = '\nStack trace:\n*'
-else:
- STACK_TRACE_TEMPLATE = ''
- # unittest.main() can't handle unknown flags
- sys.argv.remove(NO_STACKTRACE_SUPPORT_FLAG)
-
-EXPECTED_NON_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="24" failures="4" disabled="2" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
- <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="Succeeds" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
- </testsuite>
- <testsuite name="FailedTest" tests="1" failures="1" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="Fails" status="run" result="completed" time="*" timestamp="*" classname="FailedTest">
- <failure message="gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
-Expected equality of these values:
- 1
- 2%(stack)s]]></failure>
- </testcase>
- </testsuite>
- <testsuite name="MixedResultTest" tests="3" failures="1" disabled="1" errors="0" time="*" timestamp="*">
- <testcase name="Succeeds" status="run" result="completed" time="*" timestamp="*" classname="MixedResultTest"/>
- <testcase name="Fails" status="run" result="completed" time="*" timestamp="*" classname="MixedResultTest">
- <failure message="gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 1
 2" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
-Expected equality of these values:
- 1
- 2%(stack)s]]></failure>
- <failure message="gtest_xml_output_unittest_.cc:*
Expected equality of these values:
 2
 3" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
-Expected equality of these values:
- 2
- 3%(stack)s]]></failure>
- </testcase>
- <testcase name="DISABLED_test" status="notrun" result="suppressed" time="*" timestamp="*" classname="MixedResultTest"/>
- </testsuite>
- <testsuite name="XmlQuotingTest" tests="1" failures="1" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="OutputsCData" status="run" result="completed" time="*" timestamp="*" classname="XmlQuotingTest">
- <failure message="gtest_xml_output_unittest_.cc:*
Failed
XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]></top>" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
-Failed
-XML output: <?xml encoding="utf-8"><top><![CDATA[cdata text]]>]]><![CDATA[</top>%(stack)s]]></failure>
- </testcase>
- </testsuite>
- <testsuite name="InvalidCharactersTest" tests="1" failures="1" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="InvalidCharactersInMessage" status="run" result="completed" time="*" timestamp="*" classname="InvalidCharactersTest">
- <failure message="gtest_xml_output_unittest_.cc:*
Failed
Invalid characters in brackets []" type=""><![CDATA[gtest_xml_output_unittest_.cc:*
-Failed
-Invalid characters in brackets []%(stack)s]]></failure>
- </testcase>
- </testsuite>
- <testsuite name="DisabledTest" tests="1" failures="0" disabled="1" errors="0" time="*" timestamp="*">
- <testcase name="DISABLED_test_not_run" status="notrun" result="suppressed" time="*" timestamp="*" classname="DisabledTest"/>
- </testsuite>
- <testsuite name="SkippedTest" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="Skipped" status="run" result="skipped" time="*" timestamp="*" classname="SkippedTest"/>
- </testsuite>
- <testsuite name="PropertyRecordingTest" tests="4" failures="0" disabled="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
- <testcase name="OneProperty" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
- <properties>
- <property name="key_1" value="1"/>
- </properties>
- </testcase>
- <testcase name="IntValuedProperty" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
- <properties>
- <property name="key_int" value="1"/>
- </properties>
- </testcase>
- <testcase name="ThreeProperties" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
- <properties>
- <property name="key_1" value="1"/>
- <property name="key_2" value="2"/>
- <property name="key_3" value="3"/>
- </properties>
- </testcase>
- <testcase name="TwoValuesForOneKeyUsesLastValue" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
- <properties>
- <property name="key_1" value="2"/>
- </properties>
- </testcase>
- </testsuite>
- <testsuite name="NoFixtureTest" tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="RecordProperty" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
- <properties>
- <property name="key" value="1"/>
- </properties>
- </testcase>
- <testcase name="ExternalUtilityThatCallsRecordIntValuedProperty" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
- <properties>
- <property name="key_for_utility_int" value="1"/>
- </properties>
- </testcase>
- <testcase name="ExternalUtilityThatCallsRecordStringValuedProperty" status="run" result="completed" time="*" timestamp="*" classname="NoFixtureTest">
- <properties>
- <property name="key_for_utility_string" value="1"/>
- </properties>
- </testcase>
- </testsuite>
- <testsuite name="Single/ValueParamTest" tests="4" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="HasValueParamAttribute/0" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- <testcase name="HasValueParamAttribute/1" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- <testcase name="AnotherTestThatHasValueParamAttribute/0" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- <testcase name="AnotherTestThatHasValueParamAttribute/1" value_param="42" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- </testsuite>
- <testsuite name="TypedTest/0" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="HasTypeParamAttribute" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/0" />
- </testsuite>
- <testsuite name="TypedTest/1" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="HasTypeParamAttribute" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="TypedTest/1" />
- </testsuite>
- <testsuite name="Single/TypeParameterizedTestSuite/0" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="HasTypeParamAttribute" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/0" />
- </testsuite>
- <testsuite name="Single/TypeParameterizedTestSuite/1" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="HasTypeParamAttribute" type_param="*" status="run" result="completed" time="*" timestamp="*" classname="Single/TypeParameterizedTestSuite/1" />
- </testsuite>
-</testsuites>""" % {
- 'stack': STACK_TRACE_TEMPLATE
-}
-
-EXPECTED_FILTERED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="1" failures="0" disabled="0" errors="0" time="*"
- timestamp="*" name="AllTests" ad_hoc_property="42">
- <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0"
- errors="0" time="*" timestamp="*">
- <testcase name="Succeeds" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
- </testsuite>
-</testsuites>"""
-
-EXPECTED_SHARDED_TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="3" failures="0" disabled="0" errors="0" time="*" timestamp="*" name="AllTests" ad_hoc_property="42">
- <testsuite name="SuccessfulTest" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="Succeeds" status="run" result="completed" time="*" timestamp="*" classname="SuccessfulTest"/>
- </testsuite>
- <testsuite name="PropertyRecordingTest" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*" SetUpTestSuite="yes" TearDownTestSuite="aye">
- <testcase name="TwoValuesForOneKeyUsesLastValue" status="run" result="completed" time="*" timestamp="*" classname="PropertyRecordingTest">
- <properties>
- <property name="key_1" value="2"/>
- </properties>
- </testcase>
- </testsuite>
- <testsuite name="Single/ValueParamTest" tests="1" failures="0" disabled="0" errors="0" time="*" timestamp="*">
- <testcase name="AnotherTestThatHasValueParamAttribute/0" value_param="33" status="run" result="completed" time="*" timestamp="*" classname="Single/ValueParamTest" />
- </testsuite>
-</testsuites>"""
-
-EXPECTED_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
-<testsuites tests="0" failures="0" disabled="0" errors="0" time="*"
- timestamp="*" name="AllTests">
-</testsuites>"""
-
-GTEST_PROGRAM_PATH = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
-
-SUPPORTS_TYPED_TESTS = 'TypedTest' in gtest_test_utils.Subprocess(
- [GTEST_PROGRAM_PATH, GTEST_LIST_TESTS_FLAG], capture_stderr=False).output
-
-
-class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
- """
- Unit test for Google Test's XML output functionality.
- """
-
- # This test currently breaks on platforms that do not support typed and
- # type-parameterized tests, so we don't run it under them.
- if SUPPORTS_TYPED_TESTS:
- def testNonEmptyXmlOutput(self):
- """
- Runs a test program that generates a non-empty XML output, and
- tests that the XML output is expected.
- """
- self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
-
- def testEmptyXmlOutput(self):
- """Verifies XML output for a Google Test binary without actual tests.
-
- Runs a test program that generates an empty XML output, and
- tests that the XML output is expected.
- """
-
- self._TestXmlOutput('gtest_no_test_unittest', EXPECTED_EMPTY_XML, 0)
-
- def testTimestampValue(self):
- """Checks whether the timestamp attribute in the XML output is valid.
-
- Runs a test program that generates an empty XML output, and checks if
- the timestamp attribute in the testsuites tag is valid.
- """
- actual = self._GetXmlOutput('gtest_no_test_unittest', [], {}, 0)
- date_time_str = actual.documentElement.getAttributeNode('timestamp').value
- # datetime.strptime() is only available in Python 2.5+ so we have to
- # parse the expected datetime manually.
- match = re.match(r'(\d+)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)', date_time_str)
- self.assertTrue(
- re.match,
- 'XML datettime string %s has incorrect format' % date_time_str)
- date_time_from_xml = datetime.datetime(
- year=int(match.group(1)), month=int(match.group(2)),
- day=int(match.group(3)), hour=int(match.group(4)),
- minute=int(match.group(5)), second=int(match.group(6)))
-
- time_delta = abs(datetime.datetime.now() - date_time_from_xml)
- # timestamp value should be near the current local time
- self.assertTrue(time_delta < datetime.timedelta(seconds=600),
- 'time_delta is %s' % time_delta)
- actual.unlink()
-
- def testDefaultOutputFile(self):
- """
- Confirms that Google Test produces an XML output file with the expected
- default name if no name is explicitly specified.
- """
- output_file = os.path.join(gtest_test_utils.GetTempDir(),
- GTEST_DEFAULT_OUTPUT_FILE)
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(
- 'gtest_no_test_unittest')
- try:
- os.remove(output_file)
- except OSError:
- e = sys.exc_info()[1]
- if e.errno != errno.ENOENT:
- raise
-
- p = gtest_test_utils.Subprocess(
- [gtest_prog_path, '%s=xml' % GTEST_OUTPUT_FLAG],
- working_dir=gtest_test_utils.GetTempDir())
- self.assert_(p.exited)
- self.assertEquals(0, p.exit_code)
- self.assert_(os.path.isfile(output_file))
-
- def testSuppressedXmlOutput(self):
- """
- Tests that no XML file is generated if the default XML listener is
- shut down before RUN_ALL_TESTS is invoked.
- """
-
- xml_path = os.path.join(gtest_test_utils.GetTempDir(),
- GTEST_PROGRAM_NAME + 'out.xml')
- if os.path.isfile(xml_path):
- os.remove(xml_path)
-
- command = [GTEST_PROGRAM_PATH,
- '%s=xml:%s' % (GTEST_OUTPUT_FLAG, xml_path),
- '--shut_down_xml']
- p = gtest_test_utils.Subprocess(command)
- if p.terminated_by_signal:
- # p.signal is available only if p.terminated_by_signal is True.
- self.assertFalse(
- p.terminated_by_signal,
- '%s was killed by signal %d' % (GTEST_PROGRAM_NAME, p.signal))
- else:
- self.assert_(p.exited)
- self.assertEquals(1, p.exit_code,
- "'%s' exited with code %s, which doesn't match "
- 'the expected exit code %s.'
- % (command, p.exit_code, 1))
-
- self.assert_(not os.path.isfile(xml_path))
-
- def testFilteredTestXmlOutput(self):
- """Verifies XML output when a filter is applied.
-
- Runs a test program that executes only some tests and verifies that
- non-selected tests do not show up in the XML output.
- """
-
- self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_FILTERED_TEST_XML, 0,
- extra_args=['%s=SuccessfulTest.*' % GTEST_FILTER_FLAG])
-
- def testShardedTestXmlOutput(self):
- """Verifies XML output when run using multiple shards.
-
- Runs a test program that executes only one shard and verifies that tests
- from other shards do not show up in the XML output.
- """
-
- self._TestXmlOutput(
- GTEST_PROGRAM_NAME,
- EXPECTED_SHARDED_TEST_XML,
- 0,
- extra_env={SHARD_INDEX_ENV_VAR: '0',
- TOTAL_SHARDS_ENV_VAR: '10'})
-
- def _GetXmlOutput(self, gtest_prog_name, extra_args, extra_env,
- expected_exit_code):
- """
- Returns the xml output generated by running the program gtest_prog_name.
- Furthermore, the program's exit code must be expected_exit_code.
- """
- xml_path = os.path.join(gtest_test_utils.GetTempDir(),
- gtest_prog_name + 'out.xml')
- gtest_prog_path = gtest_test_utils.GetTestExecutablePath(gtest_prog_name)
-
- command = ([gtest_prog_path, '%s=xml:%s' % (GTEST_OUTPUT_FLAG, xml_path)] +
- extra_args)
- environ_copy = os.environ.copy()
- if extra_env:
- environ_copy.update(extra_env)
- p = gtest_test_utils.Subprocess(command, env=environ_copy)
-
- if p.terminated_by_signal:
- self.assert_(False,
- '%s was killed by signal %d' % (gtest_prog_name, p.signal))
- else:
- self.assert_(p.exited)
- self.assertEquals(expected_exit_code, p.exit_code,
- "'%s' exited with code %s, which doesn't match "
- 'the expected exit code %s.'
- % (command, p.exit_code, expected_exit_code))
- actual = minidom.parse(xml_path)
- return actual
-
- def _TestXmlOutput(self, gtest_prog_name, expected_xml,
- expected_exit_code, extra_args=None, extra_env=None):
- """
- Asserts that the XML document generated by running the program
- gtest_prog_name matches expected_xml, a string containing another
- XML document. Furthermore, the program's exit code must be
- expected_exit_code.
- """
-
- actual = self._GetXmlOutput(gtest_prog_name, extra_args or [],
- extra_env or {}, expected_exit_code)
- expected = minidom.parseString(expected_xml)
- self.NormalizeXml(actual.documentElement)
- self.AssertEquivalentNodes(expected.documentElement,
- actual.documentElement)
- expected.unlink()
- actual.unlink()
-
-
-if __name__ == '__main__':
- os.environ['GTEST_STACK_TRACE_DEPTH'] = '1'
- gtest_test_utils.Main()
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Unit test for Google Test XML output.
-//
-// A user can specify XML output in a Google Test program to run via
-// either the GTEST_OUTPUT environment variable or the --gtest_output
-// flag. This is used for testing such functionality.
-//
-// This program will be invoked from a Python unit test. Don't run it
-// directly.
-
-#include "gtest/gtest.h"
-
-using ::testing::InitGoogleTest;
-using ::testing::TestEventListeners;
-using ::testing::TestWithParam;
-using ::testing::UnitTest;
-using ::testing::Test;
-using ::testing::Values;
-
-class SuccessfulTest : public Test {
-};
-
-TEST_F(SuccessfulTest, Succeeds) {
- SUCCEED() << "This is a success.";
- ASSERT_EQ(1, 1);
-}
-
-class FailedTest : public Test {
-};
-
-TEST_F(FailedTest, Fails) {
- ASSERT_EQ(1, 2);
-}
-
-class DisabledTest : public Test {
-};
-
-TEST_F(DisabledTest, DISABLED_test_not_run) {
- FAIL() << "Unexpected failure: Disabled test should not be run";
-}
-
-class SkippedTest : public Test {
-};
-
-TEST_F(SkippedTest, Skipped) {
- GTEST_SKIP();
-}
-
-TEST(MixedResultTest, Succeeds) {
- EXPECT_EQ(1, 1);
- ASSERT_EQ(1, 1);
-}
-
-TEST(MixedResultTest, Fails) {
- EXPECT_EQ(1, 2);
- ASSERT_EQ(2, 3);
-}
-
-TEST(MixedResultTest, DISABLED_test) {
- FAIL() << "Unexpected failure: Disabled test should not be run";
-}
-
-TEST(XmlQuotingTest, OutputsCData) {
- FAIL() << "XML output: "
- "<?xml encoding=\"utf-8\"><top><![CDATA[cdata text]]></top>";
-}
-
-// Helps to test that invalid characters produced by test code do not make
-// it into the XML file.
-TEST(InvalidCharactersTest, InvalidCharactersInMessage) {
- FAIL() << "Invalid characters in brackets [\x1\x2]";
-}
-
-class PropertyRecordingTest : public Test {
- public:
- static void SetUpTestSuite() { RecordProperty("SetUpTestSuite", "yes"); }
- static void TearDownTestSuite() {
- RecordProperty("TearDownTestSuite", "aye");
- }
-};
-
-TEST_F(PropertyRecordingTest, OneProperty) {
- RecordProperty("key_1", "1");
-}
-
-TEST_F(PropertyRecordingTest, IntValuedProperty) {
- RecordProperty("key_int", 1);
-}
-
-TEST_F(PropertyRecordingTest, ThreeProperties) {
- RecordProperty("key_1", "1");
- RecordProperty("key_2", "2");
- RecordProperty("key_3", "3");
-}
-
-TEST_F(PropertyRecordingTest, TwoValuesForOneKeyUsesLastValue) {
- RecordProperty("key_1", "1");
- RecordProperty("key_1", "2");
-}
-
-TEST(NoFixtureTest, RecordProperty) {
- RecordProperty("key", "1");
-}
-
-void ExternalUtilityThatCallsRecordProperty(const std::string& key, int value) {
- testing::Test::RecordProperty(key, value);
-}
-
-void ExternalUtilityThatCallsRecordProperty(const std::string& key,
- const std::string& value) {
- testing::Test::RecordProperty(key, value);
-}
-
-TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
- ExternalUtilityThatCallsRecordProperty("key_for_utility_int", 1);
-}
-
-TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
- ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
-}
-
-// Verifies that the test parameter value is output in the 'value_param'
-// XML attribute for value-parameterized tests.
-class ValueParamTest : public TestWithParam<int> {};
-TEST_P(ValueParamTest, HasValueParamAttribute) {}
-TEST_P(ValueParamTest, AnotherTestThatHasValueParamAttribute) {}
-INSTANTIATE_TEST_SUITE_P(Single, ValueParamTest, Values(33, 42));
-
-#if GTEST_HAS_TYPED_TEST
-// Verifies that the type parameter name is output in the 'type_param'
-// XML attribute for typed tests.
-template <typename T> class TypedTest : public Test {};
-typedef testing::Types<int, long> TypedTestTypes;
-TYPED_TEST_SUITE(TypedTest, TypedTestTypes);
-TYPED_TEST(TypedTest, HasTypeParamAttribute) {}
-#endif
-
-#if GTEST_HAS_TYPED_TEST_P
-// Verifies that the type parameter name is output in the 'type_param'
-// XML attribute for type-parameterized tests.
-template <typename T>
-class TypeParameterizedTestSuite : public Test {};
-TYPED_TEST_SUITE_P(TypeParameterizedTestSuite);
-TYPED_TEST_P(TypeParameterizedTestSuite, HasTypeParamAttribute) {}
-REGISTER_TYPED_TEST_SUITE_P(TypeParameterizedTestSuite, HasTypeParamAttribute);
-typedef testing::Types<int, long> TypeParameterizedTestSuiteTypes; // NOLINT
-INSTANTIATE_TYPED_TEST_SUITE_P(Single, TypeParameterizedTestSuite,
- TypeParameterizedTestSuiteTypes);
-#endif
-
-int main(int argc, char** argv) {
- InitGoogleTest(&argc, argv);
-
- if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
- TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
- delete listeners.Release(listeners.default_xml_generator());
- }
- testing::Test::RecordProperty("ad_hoc_property", "42");
- return RUN_ALL_TESTS();
-}
+++ /dev/null
-# Copyright 2006, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Unit test utilities for gtest_xml_output"""
-
-import re
-from xml.dom import minidom, Node
-import gtest_test_utils
-
-GTEST_DEFAULT_OUTPUT_FILE = 'test_detail.xml'
-
-class GTestXMLTestCase(gtest_test_utils.TestCase):
- """
- Base class for tests of Google Test's XML output functionality.
- """
-
-
- def AssertEquivalentNodes(self, expected_node, actual_node):
- """
- Asserts that actual_node (a DOM node object) is equivalent to
- expected_node (another DOM node object), in that either both of
- them are CDATA nodes and have the same value, or both are DOM
- elements and actual_node meets all of the following conditions:
-
- * It has the same tag name as expected_node.
- * It has the same set of attributes as expected_node, each with
- the same value as the corresponding attribute of expected_node.
- Exceptions are any attribute named "time", which needs only be
- convertible to a floating-point number and any attribute named
- "type_param" which only has to be non-empty.
- * It has an equivalent set of child nodes (including elements and
- CDATA sections) as expected_node. Note that we ignore the
- order of the children as they are not guaranteed to be in any
- particular order.
- """
-
- if expected_node.nodeType == Node.CDATA_SECTION_NODE:
- self.assertEquals(Node.CDATA_SECTION_NODE, actual_node.nodeType)
- self.assertEquals(expected_node.nodeValue, actual_node.nodeValue)
- return
-
- self.assertEquals(Node.ELEMENT_NODE, actual_node.nodeType)
- self.assertEquals(Node.ELEMENT_NODE, expected_node.nodeType)
- self.assertEquals(expected_node.tagName, actual_node.tagName)
-
- expected_attributes = expected_node.attributes
- actual_attributes = actual_node .attributes
- self.assertEquals(
- expected_attributes.length, actual_attributes.length,
- 'attribute numbers differ in element %s:\nExpected: %r\nActual: %r' % (
- actual_node.tagName, expected_attributes.keys(),
- actual_attributes.keys()))
- for i in range(expected_attributes.length):
- expected_attr = expected_attributes.item(i)
- actual_attr = actual_attributes.get(expected_attr.name)
- self.assert_(
- actual_attr is not None,
- 'expected attribute %s not found in element %s' %
- (expected_attr.name, actual_node.tagName))
- self.assertEquals(
- expected_attr.value, actual_attr.value,
- ' values of attribute %s in element %s differ: %s vs %s' %
- (expected_attr.name, actual_node.tagName,
- expected_attr.value, actual_attr.value))
-
- expected_children = self._GetChildren(expected_node)
- actual_children = self._GetChildren(actual_node)
- self.assertEquals(
- len(expected_children), len(actual_children),
- 'number of child elements differ in element ' + actual_node.tagName)
- for child_id, child in expected_children.items():
- self.assert_(child_id in actual_children,
- '<%s> is not in <%s> (in element %s)' %
- (child_id, actual_children, actual_node.tagName))
- self.AssertEquivalentNodes(child, actual_children[child_id])
-
- identifying_attribute = {
- 'testsuites': 'name',
- 'testsuite': 'name',
- 'testcase': 'name',
- 'failure': 'message',
- 'property': 'name',
- }
-
- def _GetChildren(self, element):
- """
- Fetches all of the child nodes of element, a DOM Element object.
- Returns them as the values of a dictionary keyed by the IDs of the
- children. For <testsuites>, <testsuite>, <testcase>, and <property>
- elements, the ID is the value of their "name" attribute; for <failure>
- elements, it is the value of the "message" attribute; for <properties>
- elements, it is the value of their parent's "name" attribute plus the
- literal string "properties"; CDATA sections and non-whitespace
- text nodes are concatenated into a single CDATA section with ID
- "detail". An exception is raised if any element other than the above
- four is encountered, if two child elements with the same identifying
- attributes are encountered, or if any other type of node is encountered.
- """
-
- children = {}
- for child in element.childNodes:
- if child.nodeType == Node.ELEMENT_NODE:
- if child.tagName == 'properties':
- self.assert_(child.parentNode is not None,
- 'Encountered <properties> element without a parent')
- child_id = child.parentNode.getAttribute('name') + '-properties'
- else:
- self.assert_(child.tagName in self.identifying_attribute,
- 'Encountered unknown element <%s>' % child.tagName)
- child_id = child.getAttribute(
- self.identifying_attribute[child.tagName])
- self.assert_(child_id not in children)
- children[child_id] = child
- elif child.nodeType in [Node.TEXT_NODE, Node.CDATA_SECTION_NODE]:
- if 'detail' not in children:
- if (child.nodeType == Node.CDATA_SECTION_NODE or
- not child.nodeValue.isspace()):
- children['detail'] = child.ownerDocument.createCDATASection(
- child.nodeValue)
- else:
- children['detail'].nodeValue += child.nodeValue
- else:
- self.fail('Encountered unexpected node type %d' % child.nodeType)
- return children
-
- def NormalizeXml(self, element):
- """
- Normalizes Google Test's XML output to eliminate references to transient
- information that may change from run to run.
-
- * The "time" attribute of <testsuites>, <testsuite> and <testcase>
- elements is replaced with a single asterisk, if it contains
- only digit characters.
- * The "timestamp" attribute of <testsuites> elements is replaced with a
- single asterisk, if it contains a valid ISO8601 datetime value.
- * The "type_param" attribute of <testcase> elements is replaced with a
- single asterisk (if it sn non-empty) as it is the type name returned
- by the compiler and is platform dependent.
- * The line info reported in the first line of the "message"
- attribute and CDATA section of <failure> elements is replaced with the
- file's basename and a single asterisk for the line number.
- * The directory names in file paths are removed.
- * The stack traces are removed.
- """
-
- if element.tagName in ('testsuites', 'testsuite', 'testcase'):
- timestamp = element.getAttributeNode('timestamp')
- timestamp.value = re.sub(r'^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d$',
- '*', timestamp.value)
- if element.tagName in ('testsuites', 'testsuite', 'testcase'):
- time = element.getAttributeNode('time')
- time.value = re.sub(r'^\d+(\.\d+)?$', '*', time.value)
- type_param = element.getAttributeNode('type_param')
- if type_param and type_param.value:
- type_param.value = '*'
- elif element.tagName == 'failure':
- source_line_pat = r'^.*[/\\](.*:)\d+\n'
- # Replaces the source line information with a normalized form.
- message = element.getAttributeNode('message')
- message.value = re.sub(source_line_pat, '\\1*\n', message.value)
- for child in element.childNodes:
- if child.nodeType == Node.CDATA_SECTION_NODE:
- # Replaces the source line information with a normalized form.
- cdata = re.sub(source_line_pat, '\\1*\n', child.nodeValue)
- # Removes the actual stack trace.
- child.nodeValue = re.sub(r'Stack trace:\n(.|\n)*',
- 'Stack trace:\n*', cdata)
- for child in element.childNodes:
- if child.nodeType == Node.ELEMENT_NODE:
- self.NormalizeXml(child)
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// This is part of the unit test for gtest_prod.h.
-
-#include "production.h"
-
-PrivateCode::PrivateCode() : x_(0) {}
+++ /dev/null
-// Copyright 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-//
-// This is part of the unit test for gtest_prod.h.
-
-#ifndef GTEST_TEST_PRODUCTION_H_
-#define GTEST_TEST_PRODUCTION_H_
-
-#include "gtest/gtest_prod.h"
-
-class PrivateCode {
- public:
- // Declares a friend test that does not use a fixture.
- FRIEND_TEST(PrivateCodeTest, CanAccessPrivateMembers);
-
- // Declares a friend test that uses a fixture.
- FRIEND_TEST(PrivateCodeFixtureTest, CanAccessPrivateMembers);
-
- PrivateCode();
-
- int x() const { return x_; }
- private:
- void set_x(int an_x) { x_ = an_x; }
- int x_;
-};
-
-#endif // GTEST_TEST_PRODUCTION_H_
+++ /dev/null
-Susumu Yata <susumu.yata@gmail.com>
+++ /dev/null
-include_directories(include)
-include_directories(lib)
-
-set(
- LIBMARISA_SOURCES
- lib/marisa/trie.cc
- lib/marisa/agent.cc
- lib/marisa/grimoire/io/reader.cc
- lib/marisa/grimoire/io/writer.cc
- lib/marisa/grimoire/io/mapper.cc
- lib/marisa/grimoire/trie/louds-trie.cc
- lib/marisa/grimoire/trie/tail.cc
- lib/marisa/grimoire/vector/bit-vector.cc
- lib/marisa/keyset.cc
-)
-
-add_library(marisa STATIC ${LIBMARISA_SOURCES})
-set_target_properties(marisa PROPERTIES POSITION_INDEPENDENT_CODE ON)
-source_group(marisa FILES ${LIBMARISA_SOURCES})
+++ /dev/null
-#ifndef MARISA_H_
-#define MARISA_H_
-
-// "marisa/stdio.h" includes <cstdio> for I/O using std::FILE.
-#include "marisa/stdio.h"
-
-// "marisa/iostream.h" includes <iosfwd> for I/O using std::iostream.
-#include "marisa/iostream.h"
-
-// You can use <marisa/trie.h> instead of <marisa.h> if you don't need the
-// above I/O interfaces and don't want to include the above I/O headers.
-#include "marisa/trie.h"
-
-#endif // MARISA_H_
+++ /dev/null
-#ifndef MARISA_AGENT_H_
-#define MARISA_AGENT_H_
-
-#include "marisa/key.h"
-#include "marisa/query.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class State;
-
-} // namespace trie
-} // namespace grimoire
-
-class Agent {
- public:
- Agent();
- ~Agent();
-
- const Query &query() const {
- return query_;
- }
- const Key &key() const {
- return key_;
- }
-
- void set_query(const char *str);
- void set_query(const char *ptr, std::size_t length);
- void set_query(std::size_t key_id);
-
- const grimoire::trie::State &state() const {
- return *state_;
- }
- grimoire::trie::State &state() {
- return *state_;
- }
-
- void set_key(const char *str) {
- MARISA_DEBUG_IF(str == NULL, MARISA_NULL_ERROR);
- key_.set_str(str);
- }
- void set_key(const char *ptr, std::size_t length) {
- MARISA_DEBUG_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- MARISA_DEBUG_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- key_.set_str(ptr, length);
- }
- void set_key(std::size_t id) {
- MARISA_DEBUG_IF(id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- key_.set_id(id);
- }
-
- bool has_state() const {
- return state_.get() != NULL;
- }
- void init_state();
-
- void clear();
- void swap(Agent &rhs);
-
- private:
- Query query_;
- Key key_;
- scoped_ptr<grimoire::trie::State> state_;
-
- // Disallows copy and assignment.
- Agent(const Agent &);
- Agent &operator=(const Agent &);
-};
-
-} // namespace marisa
-
-#endif // MARISA_AGENT_H_
+++ /dev/null
-#ifndef MARISA_BASE_H_
-#define MARISA_BASE_H_
-
-// Old Visual C++ does not provide stdint.h.
-#ifndef _MSC_VER
- #include <stdint.h>
-#endif // _MSC_VER
-
-#ifdef __cplusplus
- #include <cstddef>
-#else // __cplusplus
- #include <stddef.h>
-#endif // __cplusplus
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-#ifdef _MSC_VER
-typedef unsigned __int8 marisa_uint8;
-typedef unsigned __int16 marisa_uint16;
-typedef unsigned __int32 marisa_uint32;
-typedef unsigned __int64 marisa_uint64;
-#else // _MSC_VER
-typedef uint8_t marisa_uint8;
-typedef uint16_t marisa_uint16;
-typedef uint32_t marisa_uint32;
-typedef uint64_t marisa_uint64;
-#endif // _MSC_VER
-
-#if defined(_WIN64) || defined(__amd64__) || defined(__x86_64__) || \
- defined(__ia64__) || defined(__ppc64__) || defined(__powerpc64__) || \
- defined(__sparc64__) || defined(__mips64__) || defined(__aarch64__) || \
- defined(__s390x__)
- #define MARISA_WORD_SIZE 64
-#else // defined(_WIN64), etc.
- #define MARISA_WORD_SIZE 32
-#endif // defined(_WIN64), etc.
-
-//#define MARISA_WORD_SIZE (sizeof(void *) * 8)
-
-#define MARISA_UINT8_MAX ((marisa_uint8)~(marisa_uint8)0)
-#define MARISA_UINT16_MAX ((marisa_uint16)~(marisa_uint16)0)
-#define MARISA_UINT32_MAX ((marisa_uint32)~(marisa_uint32)0)
-#define MARISA_UINT64_MAX ((marisa_uint64)~(marisa_uint64)0)
-#define MARISA_SIZE_MAX ((size_t)~(size_t)0)
-
-#define MARISA_INVALID_LINK_ID MARISA_UINT32_MAX
-#define MARISA_INVALID_KEY_ID MARISA_UINT32_MAX
-#define MARISA_INVALID_EXTRA (MARISA_UINT32_MAX >> 8)
-
-// Error codes are defined as members of marisa_error_code. This library throws
-// an exception with one of the error codes when an error occurs.
-typedef enum marisa_error_code_ {
- // MARISA_OK means that a requested operation has succeeded. In practice, an
- // exception never has MARISA_OK because it is not an error.
- MARISA_OK = 0,
-
- // MARISA_STATE_ERROR means that an object was not ready for a requested
- // operation. For example, an operation to modify a fixed vector throws an
- // exception with MARISA_STATE_ERROR.
- MARISA_STATE_ERROR = 1,
-
- // MARISA_NULL_ERROR means that an invalid NULL pointer has been given.
- MARISA_NULL_ERROR = 2,
-
- // MARISA_BOUND_ERROR means that an operation has tried to access an out of
- // range address.
- MARISA_BOUND_ERROR = 3,
-
- // MARISA_RANGE_ERROR means that an out of range value has appeared in
- // operation.
- MARISA_RANGE_ERROR = 4,
-
- // MARISA_CODE_ERROR means that an undefined code has appeared in operation.
- MARISA_CODE_ERROR = 5,
-
- // MARISA_RESET_ERROR means that a smart pointer has tried to reset itself.
- MARISA_RESET_ERROR = 6,
-
- // MARISA_SIZE_ERROR means that a size has exceeded a library limitation.
- MARISA_SIZE_ERROR = 7,
-
- // MARISA_MEMORY_ERROR means that a memory allocation has failed.
- MARISA_MEMORY_ERROR = 8,
-
- // MARISA_IO_ERROR means that an I/O operation has failed.
- MARISA_IO_ERROR = 9,
-
- // MARISA_FORMAT_ERROR means that input was in invalid format.
- MARISA_FORMAT_ERROR = 10,
-} marisa_error_code;
-
-// Min/max values, flags and masks for dictionary settings are defined below.
-// Please note that unspecified settings will be replaced with the default
-// settings. For example, 0 is equivalent to (MARISA_DEFAULT_NUM_TRIES |
-// MARISA_DEFAULT_TRIE | MARISA_DEFAULT_TAIL | MARISA_DEFAULT_ORDER).
-
-// A dictionary consists of 3 tries in default. Usually more tries make a
-// dictionary space-efficient but time-inefficient.
-typedef enum marisa_num_tries_ {
- MARISA_MIN_NUM_TRIES = 0x00001,
- MARISA_MAX_NUM_TRIES = 0x0007F,
- MARISA_DEFAULT_NUM_TRIES = 0x00003,
-} marisa_num_tries;
-
-// This library uses a cache technique to accelerate search functions. The
-// following enumerated type marisa_cache_level gives a list of available cache
-// size options. A larger cache enables faster search but takes a more space.
-typedef enum marisa_cache_level_ {
- MARISA_HUGE_CACHE = 0x00080,
- MARISA_LARGE_CACHE = 0x00100,
- MARISA_NORMAL_CACHE = 0x00200,
- MARISA_SMALL_CACHE = 0x00400,
- MARISA_TINY_CACHE = 0x00800,
- MARISA_DEFAULT_CACHE = MARISA_NORMAL_CACHE
-} marisa_cache_level;
-
-// This library provides 2 kinds of TAIL implementations.
-typedef enum marisa_tail_mode_ {
- // MARISA_TEXT_TAIL merges last labels as zero-terminated strings. So, it is
- // available if and only if the last labels do not contain a NULL character.
- // If MARISA_TEXT_TAIL is specified and a NULL character exists in the last
- // labels, the setting is automatically switched to MARISA_BINARY_TAIL.
- MARISA_TEXT_TAIL = 0x01000,
-
- // MARISA_BINARY_TAIL also merges last labels but as byte sequences. It uses
- // a bit vector to detect the end of a sequence, instead of NULL characters.
- // So, MARISA_BINARY_TAIL requires a larger space if the average length of
- // labels is greater than 8.
- MARISA_BINARY_TAIL = 0x02000,
-
- MARISA_DEFAULT_TAIL = MARISA_TEXT_TAIL,
-} marisa_tail_mode;
-
-// The arrangement of nodes affects the time cost of matching and the order of
-// predictive search.
-typedef enum marisa_node_order_ {
- // MARISA_LABEL_ORDER arranges nodes in ascending label order.
- // MARISA_LABEL_ORDER is useful if an application needs to predict keys in
- // label order.
- MARISA_LABEL_ORDER = 0x10000,
-
- // MARISA_WEIGHT_ORDER arranges nodes in descending weight order.
- // MARISA_WEIGHT_ORDER is generally a better choice because it enables faster
- // matching.
- MARISA_WEIGHT_ORDER = 0x20000,
-
- MARISA_DEFAULT_ORDER = MARISA_WEIGHT_ORDER,
-} marisa_node_order;
-
-typedef enum marisa_config_mask_ {
- MARISA_NUM_TRIES_MASK = 0x0007F,
- MARISA_CACHE_LEVEL_MASK = 0x00F80,
- MARISA_TAIL_MODE_MASK = 0x0F000,
- MARISA_NODE_ORDER_MASK = 0xF0000,
- MARISA_CONFIG_MASK = 0xFFFFF
-} marisa_config_mask;
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#ifdef __cplusplus
-namespace marisa {
-
-typedef ::marisa_uint8 UInt8;
-typedef ::marisa_uint16 UInt16;
-typedef ::marisa_uint32 UInt32;
-typedef ::marisa_uint64 UInt64;
-
-typedef ::marisa_error_code ErrorCode;
-
-typedef ::marisa_cache_level CacheLevel;
-typedef ::marisa_tail_mode TailMode;
-typedef ::marisa_node_order NodeOrder;
-
-template <typename T>
-inline void swap(T &lhs, T &rhs) {
- T temp = lhs;
- lhs = rhs;
- rhs = temp;
-}
-
-} // namespace marisa
-#endif // __cplusplus
-
-#ifdef __cplusplus
- #include "marisa/exception.h"
- #include "marisa/scoped-ptr.h"
- #include "marisa/scoped-array.h"
-#endif // __cplusplus
-
-#endif // MARISA_BASE_H_
+++ /dev/null
-#ifndef MARISA_EXCEPTION_H_
-#define MARISA_EXCEPTION_H_
-
-#include <exception>
-
-#include "marisa/base.h"
-
-namespace marisa {
-
-// An exception object keeps a filename, a line number, an error code and an
-// error message. The message format is as follows:
-// "__FILE__:__LINE__: error_code: error_message"
-class Exception : public std::exception {
- public:
- Exception(const char *filename, int line,
- ErrorCode error_code, const char *error_message)
- : std::exception(), filename_(filename), line_(line),
- error_code_(error_code), error_message_(error_message) {}
- Exception(const Exception &ex)
- : std::exception(), filename_(ex.filename_), line_(ex.line_),
- error_code_(ex.error_code_), error_message_(ex.error_message_) {}
- virtual ~Exception() throw() {}
-
- Exception &operator=(const Exception &rhs) {
- filename_ = rhs.filename_;
- line_ = rhs.line_;
- error_code_ = rhs.error_code_;
- error_message_ = rhs.error_message_;
- return *this;
- }
-
- const char *filename() const {
- return filename_;
- }
- int line() const {
- return line_;
- }
- ErrorCode error_code() const {
- return error_code_;
- }
- const char *error_message() const {
- return error_message_;
- }
-
- virtual const char *what() const throw() {
- return error_message_;
- }
-
- private:
- const char *filename_;
- int line_;
- ErrorCode error_code_;
- const char *error_message_;
-};
-
-// These macros are used to convert a line number to a string constant.
-#define MARISA_INT_TO_STR(value) #value
-#define MARISA_LINE_TO_STR(line) MARISA_INT_TO_STR(line)
-#define MARISA_LINE_STR MARISA_LINE_TO_STR(__LINE__)
-
-// MARISA_THROW throws an exception with a filename, a line number, an error
-// code and an error message. The message format is as follows:
-// "__FILE__:__LINE__: error_code: error_message"
-#define MARISA_THROW(error_code, error_message) \
- (throw marisa::Exception(__FILE__, __LINE__, error_code, \
- __FILE__ ":" MARISA_LINE_STR ": " #error_code ": " error_message))
-
-// MARISA_THROW_IF throws an exception if `condition' is true.
-#define MARISA_THROW_IF(condition, error_code) \
- (void)((!(condition)) || (MARISA_THROW(error_code, #condition), 0))
-
-// MARISA_DEBUG_IF is ignored if _DEBUG is undefined. So, it is useful for
-// debugging time-critical codes.
-#ifdef _DEBUG
- #define MARISA_DEBUG_IF(cond, error_code) MARISA_THROW_IF(cond, error_code)
-#else
- #define MARISA_DEBUG_IF(cond, error_code)
-#endif
-
-} // namespace marisa
-
-#endif // MARISA_EXCEPTION_H_
+++ /dev/null
-#ifndef MARISA_IOSTREAM_H_
-#define MARISA_IOSTREAM_H_
-
-#include <iosfwd>
-
-namespace marisa {
-
-class Trie;
-
-std::istream &read(std::istream &stream, Trie *trie);
-std::ostream &write(std::ostream &stream, const Trie &trie);
-
-std::istream &operator>>(std::istream &stream, Trie &trie);
-std::ostream &operator<<(std::ostream &stream, const Trie &trie);
-
-} // namespace marisa
-
-#endif // MARISA_IOSTREAM_H_
+++ /dev/null
-#ifndef MARISA_KEY_H_
-#define MARISA_KEY_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-
-class Key {
- public:
- Key() : ptr_(NULL), length_(0), union_() {
- union_.id = 0;
- }
- Key(const Key &key)
- : ptr_(key.ptr_), length_(key.length_), union_(key.union_) {}
-
- Key &operator=(const Key &key) {
- ptr_ = key.ptr_;
- length_ = key.length_;
- union_ = key.union_;
- return *this;
- }
-
- char operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= length_, MARISA_BOUND_ERROR);
- return ptr_[i];
- }
-
- void set_str(const char *str) {
- MARISA_DEBUG_IF(str == NULL, MARISA_NULL_ERROR);
- std::size_t length = 0;
- while (str[length] != '\0') {
- ++length;
- }
- MARISA_DEBUG_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- ptr_ = str;
- length_ = (UInt32)length;
- }
- void set_str(const char *ptr, std::size_t length) {
- MARISA_DEBUG_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- MARISA_DEBUG_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- ptr_ = ptr;
- length_ = (UInt32)length;
- }
- void set_id(std::size_t id) {
- MARISA_DEBUG_IF(id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- union_.id = (UInt32)id;
- }
- void set_weight(float weight) {
- union_.weight = weight;
- }
-
- const char *ptr() const {
- return ptr_;
- }
- std::size_t length() const {
- return length_;
- }
- std::size_t id() const {
- return union_.id;
- }
- float weight() const {
- return union_.weight;
- }
-
- void clear() {
- Key().swap(*this);
- }
- void swap(Key &rhs) {
- marisa::swap(ptr_, rhs.ptr_);
- marisa::swap(length_, rhs.length_);
- marisa::swap(union_.id, rhs.union_.id);
- }
-
- private:
- const char *ptr_;
- UInt32 length_;
- union Union {
- UInt32 id;
- float weight;
- } union_;
-};
-
-} // namespace marisa
-
-#endif // MARISA_KEY_H_
+++ /dev/null
-#ifndef MARISA_KEYSET_H_
-#define MARISA_KEYSET_H_
-
-#include "marisa/key.h"
-
-namespace marisa {
-
-class Keyset {
- public:
- enum {
- BASE_BLOCK_SIZE = 4096,
- EXTRA_BLOCK_SIZE = 1024,
- KEY_BLOCK_SIZE = 256
- };
-
- Keyset();
-
- void push_back(const Key &key);
- void push_back(const Key &key, char end_marker);
-
- void push_back(const char *str);
- void push_back(const char *ptr, std::size_t length, float weight = 1.0);
-
- const Key &operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
- return key_blocks_[i / KEY_BLOCK_SIZE][i % KEY_BLOCK_SIZE];
- }
- Key &operator[](std::size_t i) {
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
- return key_blocks_[i / KEY_BLOCK_SIZE][i % KEY_BLOCK_SIZE];
- }
-
- std::size_t num_keys() const {
- return size_;
- }
-
- bool empty() const {
- return size_ == 0;
- }
- std::size_t size() const {
- return size_;
- }
- std::size_t total_length() const {
- return total_length_;
- }
-
- void reset();
-
- void clear();
- void swap(Keyset &rhs);
-
- private:
- scoped_array<scoped_array<char> > base_blocks_;
- std::size_t base_blocks_size_;
- std::size_t base_blocks_capacity_;
- scoped_array<scoped_array<char> > extra_blocks_;
- std::size_t extra_blocks_size_;
- std::size_t extra_blocks_capacity_;
- scoped_array<scoped_array<Key> > key_blocks_;
- std::size_t key_blocks_size_;
- std::size_t key_blocks_capacity_;
- char *ptr_;
- std::size_t avail_;
- std::size_t size_;
- std::size_t total_length_;
-
- char *reserve(std::size_t size);
-
- void append_base_block();
- void append_extra_block(std::size_t size);
- void append_key_block();
-
- // Disallows copy and assignment.
- Keyset(const Keyset &);
- Keyset &operator=(const Keyset &);
-};
-
-} // namespace marisa
-
-#endif // MARISA_KEYSET_H_
+++ /dev/null
-#ifndef MARISA_QUERY_H_
-#define MARISA_QUERY_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-
-class Query {
- public:
- Query() : ptr_(NULL), length_(0), id_(0) {}
- Query(const Query &query)
- : ptr_(query.ptr_), length_(query.length_), id_(query.id_) {}
-
- Query &operator=(const Query &query) {
- ptr_ = query.ptr_;
- length_ = query.length_;
- id_ = query.id_;
- return *this;
- }
-
- char operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= length_, MARISA_BOUND_ERROR);
- return ptr_[i];
- }
-
- void set_str(const char *str) {
- MARISA_DEBUG_IF(str == NULL, MARISA_NULL_ERROR);
- std::size_t length = 0;
- while (str[length] != '\0') {
- ++length;
- }
- ptr_ = str;
- length_ = length;
- }
- void set_str(const char *ptr, std::size_t length) {
- MARISA_DEBUG_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- ptr_ = ptr;
- length_ = length;
- }
- void set_id(std::size_t id) {
- id_ = id;
- }
-
- const char *ptr() const {
- return ptr_;
- }
- std::size_t length() const {
- return length_;
- }
- std::size_t id() const {
- return id_;
- }
-
- void clear() {
- Query().swap(*this);
- }
- void swap(Query &rhs) {
- marisa::swap(ptr_, rhs.ptr_);
- marisa::swap(length_, rhs.length_);
- marisa::swap(id_, rhs.id_);
- }
-
- private:
- const char *ptr_;
- std::size_t length_;
- std::size_t id_;
-};
-
-} // namespace marisa
-
-#endif // MARISA_QUERY_H_
+++ /dev/null
-#ifndef MARISA_SCOPED_ARRAY_H_
-#define MARISA_SCOPED_ARRAY_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-
-template <typename T>
-class scoped_array {
- public:
- scoped_array() : array_(NULL) {}
- explicit scoped_array(T *array) : array_(array) {}
-
- ~scoped_array() {
- delete [] array_;
- }
-
- void reset(T *array = NULL) {
- MARISA_THROW_IF((array != NULL) && (array == array_), MARISA_RESET_ERROR);
- scoped_array(array).swap(*this);
- }
-
- T &operator[](std::size_t i) const {
- MARISA_DEBUG_IF(array_ == NULL, MARISA_STATE_ERROR);
- return array_[i];
- }
- T *get() const {
- return array_;
- }
-
- void clear() {
- scoped_array().swap(*this);
- }
- void swap(scoped_array &rhs) {
- marisa::swap(array_, rhs.array_);
- }
-
- private:
- T *array_;
-
- // Disallows copy and assignment.
- scoped_array(const scoped_array &);
- scoped_array &operator=(const scoped_array &);
-};
-
-} // namespace marisa
-
-#endif // MARISA_SCOPED_ARRAY_H_
+++ /dev/null
-#ifndef MARISA_SCOPED_PTR_H_
-#define MARISA_SCOPED_PTR_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-
-template <typename T>
-class scoped_ptr {
- public:
- scoped_ptr() : ptr_(NULL) {}
- explicit scoped_ptr(T *ptr) : ptr_(ptr) {}
-
- ~scoped_ptr() {
- delete ptr_;
- }
-
- void reset(T *ptr = NULL) {
- MARISA_THROW_IF((ptr != NULL) && (ptr == ptr_), MARISA_RESET_ERROR);
- scoped_ptr(ptr).swap(*this);
- }
-
- T &operator*() const {
- MARISA_DEBUG_IF(ptr_ == NULL, MARISA_STATE_ERROR);
- return *ptr_;
- }
- T *operator->() const {
- MARISA_DEBUG_IF(ptr_ == NULL, MARISA_STATE_ERROR);
- return ptr_;
- }
- T *get() const {
- return ptr_;
- }
-
- void clear() {
- scoped_ptr().swap(*this);
- }
- void swap(scoped_ptr &rhs) {
- marisa::swap(ptr_, rhs.ptr_);
- }
-
- private:
- T *ptr_;
-
- // Disallows copy and assignment.
- scoped_ptr(const scoped_ptr &);
- scoped_ptr &operator=(const scoped_ptr &);
-};
-
-} // namespace marisa
-
-#endif // MARISA_SCOPED_PTR_H_
+++ /dev/null
-#ifndef MARISA_MYSTDIO_H_
-#define MARISA_MYSTDIO_H_
-
-#include <cstdio>
-
-namespace marisa {
-
-class Trie;
-
-void fread(std::FILE *file, Trie *trie);
-void fwrite(std::FILE *file, const Trie &trie);
-
-} // namespace marisa
-
-#endif // MARISA_MYSTDIO_H_
+++ /dev/null
-#ifndef MARISA_TRIE_H_
-#define MARISA_TRIE_H_
-
-#include "marisa/keyset.h"
-#include "marisa/agent.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class LoudsTrie;
-
-} // namespace trie
-} // namespace grimoire
-
-class Trie {
- friend class TrieIO;
-
- public:
- Trie();
- ~Trie();
-
- void build(Keyset &keyset, int config_flags = 0);
-
- void mmap(const char *filename);
- void map(const void *ptr, std::size_t size);
-
- void load(const char *filename);
- void read(int fd);
-
- void save(const char *filename) const;
- void write(int fd) const;
-
- bool lookup(Agent &agent) const;
- void reverse_lookup(Agent &agent) const;
- bool common_prefix_search(Agent &agent) const;
- bool predictive_search(Agent &agent) const;
-
- std::size_t num_tries() const;
- std::size_t num_keys() const;
- std::size_t num_nodes() const;
-
- TailMode tail_mode() const;
- NodeOrder node_order() const;
-
- bool empty() const;
- std::size_t size() const;
- std::size_t total_size() const;
- std::size_t io_size() const;
-
- void clear();
- void swap(Trie &rhs);
-
- private:
- scoped_ptr<grimoire::trie::LoudsTrie> trie_;
-
- // Disallows copy and assignment.
- Trie(const Trie &);
- Trie &operator=(const Trie &);
-};
-
-} // namespace marisa
-
-#endif // MARISA_TRIE_H_
+++ /dev/null
-#include <new>
-
-#include "marisa/agent.h"
-#include "marisa/grimoire/trie.h"
-
-namespace marisa {
-
-Agent::Agent() : query_(), key_(), state_() {}
-
-Agent::~Agent() {}
-
-void Agent::set_query(const char *str) {
- MARISA_THROW_IF(str == NULL, MARISA_NULL_ERROR);
- if (state_.get() != NULL) {
- state_->reset();
- }
- query_.set_str(str);
-}
-
-void Agent::set_query(const char *ptr, std::size_t length) {
- MARISA_THROW_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- if (state_.get() != NULL) {
- state_->reset();
- }
- query_.set_str(ptr, length);
-}
-
-void Agent::set_query(std::size_t key_id) {
- if (state_.get() != NULL) {
- state_->reset();
- }
- query_.set_id(key_id);
-}
-
-void Agent::init_state() {
- MARISA_THROW_IF(state_.get() != NULL, MARISA_STATE_ERROR);
- state_.reset(new (std::nothrow) grimoire::State);
- MARISA_THROW_IF(state_.get() == NULL, MARISA_MEMORY_ERROR);
-}
-
-void Agent::clear() {
- Agent().swap(*this);
-}
-
-void Agent::swap(Agent &rhs) {
- query_.swap(rhs.query_);
- key_.swap(rhs.key_);
- state_.swap(rhs.state_);
-}
-
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_ALGORITHM_H_
-#define MARISA_GRIMOIRE_ALGORITHM_H_
-
-#include "marisa/grimoire/algorithm/sort.h"
-
-namespace marisa {
-namespace grimoire {
-
-class Algorithm {
- public:
- Algorithm() {}
-
- template <typename Iterator>
- std::size_t sort(Iterator begin, Iterator end) const {
- return algorithm::sort(begin, end);
- }
-
- private:
- Algorithm(const Algorithm &);
- Algorithm &operator=(const Algorithm &);
-};
-
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_ALGORITHM_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_ALGORITHM_SORT_H_
-#define MARISA_GRIMOIRE_ALGORITHM_SORT_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace algorithm {
-namespace details {
-
-enum {
- MARISA_INSERTION_SORT_THRESHOLD = 10
-};
-
-template <typename T>
-int get_label(const T &unit, std::size_t depth) {
- MARISA_DEBUG_IF(depth > unit.length(), MARISA_BOUND_ERROR);
-
- return (depth < unit.length()) ? (int)(UInt8)unit[depth] : -1;
-}
-
-template <typename T>
-int median(const T &a, const T &b, const T &c, std::size_t depth) {
- const int x = get_label(a, depth);
- const int y = get_label(b, depth);
- const int z = get_label(c, depth);
- if (x < y) {
- if (y < z) {
- return y;
- } else if (x < z) {
- return z;
- }
- return x;
- } else if (x < z) {
- return x;
- } else if (y < z) {
- return z;
- }
- return y;
-}
-
-template <typename T>
-int compare(const T &lhs, const T &rhs, std::size_t depth) {
- for (std::size_t i = depth; i < lhs.length(); ++i) {
- if (i == rhs.length()) {
- return 1;
- }
- if (lhs[i] != rhs[i]) {
- return (UInt8)lhs[i] - (UInt8)rhs[i];
- }
- }
- if (lhs.length() == rhs.length()) {
- return 0;
- }
- return (lhs.length() < rhs.length()) ? -1 : 1;
-}
-
-template <typename Iterator>
-std::size_t insertion_sort(Iterator l, Iterator r, std::size_t depth) {
- MARISA_DEBUG_IF(l > r, MARISA_BOUND_ERROR);
-
- std::size_t count = 1;
- for (Iterator i = l + 1; i < r; ++i) {
- int result = 0;
- for (Iterator j = i; j > l; --j) {
- result = compare(*(j - 1), *j, depth);
- if (result <= 0) {
- break;
- }
- marisa::swap(*(j - 1), *j);
- }
- if (result != 0) {
- ++count;
- }
- }
- return count;
-}
-
-template <typename Iterator>
-std::size_t sort(Iterator l, Iterator r, std::size_t depth) {
- MARISA_DEBUG_IF(l > r, MARISA_BOUND_ERROR);
-
- std::size_t count = 0;
- while ((r - l) > MARISA_INSERTION_SORT_THRESHOLD) {
- Iterator pl = l;
- Iterator pr = r;
- Iterator pivot_l = l;
- Iterator pivot_r = r;
-
- const int pivot = median(*l, *(l + (r - l) / 2), *(r - 1), depth);
- for ( ; ; ) {
- while (pl < pr) {
- const int label = get_label(*pl, depth);
- if (label > pivot) {
- break;
- } else if (label == pivot) {
- marisa::swap(*pl, *pivot_l);
- ++pivot_l;
- }
- ++pl;
- }
- while (pl < pr) {
- const int label = get_label(*--pr, depth);
- if (label < pivot) {
- break;
- } else if (label == pivot) {
- marisa::swap(*pr, *--pivot_r);
- }
- }
- if (pl >= pr) {
- break;
- }
- marisa::swap(*pl, *pr);
- ++pl;
- }
- while (pivot_l > l) {
- marisa::swap(*--pivot_l, *--pl);
- }
- while (pivot_r < r) {
- marisa::swap(*pivot_r, *pr);
- ++pivot_r;
- ++pr;
- }
-
- if (((pl - l) > (pr - pl)) || ((r - pr) > (pr - pl))) {
- if ((pr - pl) == 1) {
- ++count;
- } else if ((pr - pl) > 1) {
- if (pivot == -1) {
- ++count;
- } else {
- count += sort(pl, pr, depth + 1);
- }
- }
-
- if ((pl - l) < (r - pr)) {
- if ((pl - l) == 1) {
- ++count;
- } else if ((pl - l) > 1) {
- count += sort(l, pl, depth);
- }
- l = pr;
- } else {
- if ((r - pr) == 1) {
- ++count;
- } else if ((r - pr) > 1) {
- count += sort(pr, r, depth);
- }
- r = pl;
- }
- } else {
- if ((pl - l) == 1) {
- ++count;
- } else if ((pl - l) > 1) {
- count += sort(l, pl, depth);
- }
-
- if ((r - pr) == 1) {
- ++count;
- } else if ((r - pr) > 1) {
- count += sort(pr, r, depth);
- }
-
- l = pl, r = pr;
- if ((pr - pl) == 1) {
- ++count;
- } else if ((pr - pl) > 1) {
- if (pivot == -1) {
- l = r;
- ++count;
- } else {
- ++depth;
- }
- }
- }
- }
-
- if ((r - l) > 1) {
- count += insertion_sort(l, r, depth);
- }
- return count;
-}
-
-} // namespace details
-
-template <typename Iterator>
-std::size_t sort(Iterator begin, Iterator end) {
- MARISA_DEBUG_IF(begin > end, MARISA_BOUND_ERROR);
- return details::sort(begin, end, 0);
-};
-
-} // namespace algorithm
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_ALGORITHM_SORT_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_INTRIN_H_
-#define MARISA_GRIMOIRE_INTRIN_H_
-
-#include "marisa/base.h"
-
-#if defined(__x86_64__) || defined(_M_X64)
- #define MARISA_X64
-#elif defined(__i386__) || defined(_M_IX86)
- #define MARISA_X86
-#else // defined(__i386__) || defined(_M_IX86)
- #ifdef MARISA_USE_POPCNT
- #undef MARISA_USE_POPCNT
- #endif // MARISA_USE_POPCNT
- #ifdef MARISA_USE_SSE4A
- #undef MARISA_USE_SSE4A
- #endif // MARISA_USE_SSE4A
- #ifdef MARISA_USE_SSE4
- #undef MARISA_USE_SSE4
- #endif // MARISA_USE_SSE4
- #ifdef MARISA_USE_SSE4_2
- #undef MARISA_USE_SSE4_2
- #endif // MARISA_USE_SSE4_2
- #ifdef MARISA_USE_SSE4_1
- #undef MARISA_USE_SSE4_1
- #endif // MARISA_USE_SSE4_1
- #ifdef MARISA_USE_SSSE3
- #undef MARISA_USE_SSSE3
- #endif // MARISA_USE_SSSE3
- #ifdef MARISA_USE_SSE3
- #undef MARISA_USE_SSE3
- #endif // MARISA_USE_SSE3
- #ifdef MARISA_USE_SSE2
- #undef MARISA_USE_SSE2
- #endif // MARISA_USE_SSE2
-#endif // defined(__i386__) || defined(_M_IX86)
-
-#ifdef MARISA_USE_POPCNT
- #ifndef MARISA_USE_SSE3
- #define MARISA_USE_SSE3
- #endif // MARISA_USE_SSE3
- #ifdef _MSC_VER
- #include <intrin.h>
- #else // _MSC_VER
- #include <popcntintrin.h>
- #endif // _MSC_VER
-#endif // MARISA_USE_POPCNT
-
-#ifdef MARISA_USE_SSE4A
- #ifndef MARISA_USE_SSE3
- #define MARISA_USE_SSE3
- #endif // MARISA_USE_SSE3
- #ifndef MARISA_USE_POPCNT
- #define MARISA_USE_POPCNT
- #endif // MARISA_USE_POPCNT
-#endif // MARISA_USE_SSE4A
-
-#ifdef MARISA_USE_SSE4
- #ifndef MARISA_USE_SSE4_2
- #define MARISA_USE_SSE4_2
- #endif // MARISA_USE_SSE4_2
-#endif // MARISA_USE_SSE4
-
-#ifdef MARISA_USE_SSE4_2
- #ifndef MARISA_USE_SSE4_1
- #define MARISA_USE_SSE4_1
- #endif // MARISA_USE_SSE4_1
- #ifndef MARISA_USE_POPCNT
- #define MARISA_USE_POPCNT
- #endif // MARISA_USE_POPCNT
-#endif // MARISA_USE_SSE4_2
-
-#ifdef MARISA_USE_SSE4_1
- #ifndef MARISA_USE_SSSE3
- #define MARISA_USE_SSSE3
- #endif // MARISA_USE_SSSE3
-#endif // MARISA_USE_SSE4_1
-
-#ifdef MARISA_USE_SSSE3
- #ifndef MARISA_USE_SSE3
- #define MARISA_USE_SSE3
- #endif // MARISA_USE_SSE3
- #ifdef MARISA_X64
- #define MARISA_X64_SSSE3
- #else // MARISA_X64
- #define MARISA_X86_SSSE3
- #endif // MAIRSA_X64
- #include <tmmintrin.h>
-#endif // MARISA_USE_SSSE3
-
-#ifdef MARISA_USE_SSE3
- #ifndef MARISA_USE_SSE2
- #define MARISA_USE_SSE2
- #endif // MARISA_USE_SSE2
-#endif // MARISA_USE_SSE3
-
-#ifdef MARISA_USE_SSE2
- #ifdef MARISA_X64
- #define MARISA_X64_SSE2
- #else // MARISA_X64
- #define MARISA_X86_SSE2
- #endif // MAIRSA_X64
- #include <emmintrin.h>
-#endif // MARISA_USE_SSE2
-
-#ifdef _MSC_VER
- #if MARISA_WORD_SIZE == 64
- #include <intrin.h>
- #pragma intrinsic(_BitScanForward64)
- #else // MARISA_WORD_SIZE == 64
- #include <intrin.h>
- #pragma intrinsic(_BitScanForward)
- #endif // MARISA_WORD_SIZE == 64
-#endif // _MSC_VER
-
-#endif // MARISA_GRIMOIRE_INTRIN_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_IO_H_
-#define MARISA_GRIMOIRE_IO_H_
-
-#include "marisa/grimoire/io/mapper.h"
-#include "marisa/grimoire/io/reader.h"
-#include "marisa/grimoire/io/writer.h"
-
-namespace marisa {
-namespace grimoire {
-
-using io::Mapper;
-using io::Reader;
-using io::Writer;
-
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_IO_H_
+++ /dev/null
-#if (defined _WIN32) || (defined _WIN64)
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <windows.h>
-#else // (defined _WIN32) || (defined _WIN64)
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <unistd.h>
-#endif // (defined _WIN32) || (defined _WIN64)
-
-#include "marisa/grimoire/io/mapper.h"
-
-namespace marisa {
-namespace grimoire {
-namespace io {
-
-#if (defined _WIN32) || (defined _WIN64)
-Mapper::Mapper()
- : ptr_(NULL), origin_(NULL), avail_(0), size_(0),
- file_(NULL), map_(NULL) {}
-#else // (defined _WIN32) || (defined _WIN64)
-Mapper::Mapper()
- : ptr_(NULL), origin_(MAP_FAILED), avail_(0), size_(0), fd_(-1) {}
-#endif // (defined _WIN32) || (defined _WIN64)
-
-#if (defined _WIN32) || (defined _WIN64)
-Mapper::~Mapper() {
- if (origin_ != NULL) {
- ::UnmapViewOfFile(origin_);
- }
-
- if (map_ != NULL) {
- ::CloseHandle(map_);
- }
-
- if (file_ != NULL) {
- ::CloseHandle(file_);
- }
-}
-#else // (defined _WIN32) || (defined _WIN64)
-Mapper::~Mapper() {
- if (origin_ != MAP_FAILED) {
- ::munmap(origin_, size_);
- }
-
- if (fd_ != -1) {
- ::close(fd_);
- }
-}
-#endif // (defined _WIN32) || (defined _WIN64)
-
-void Mapper::open(const char *filename) {
- MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
-
- Mapper temp;
- temp.open_(filename);
- swap(temp);
-}
-
-void Mapper::open(const void *ptr, std::size_t size) {
- MARISA_THROW_IF((ptr == NULL) && (size != 0), MARISA_NULL_ERROR);
-
- Mapper temp;
- temp.open_(ptr, size);
- swap(temp);
-}
-
-void Mapper::seek(std::size_t size) {
- MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
- MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR);
-
- map_data(size);
-}
-
-bool Mapper::is_open() const {
- return ptr_ != NULL;
-}
-
-void Mapper::clear() {
- Mapper().swap(*this);
-}
-
-void Mapper::swap(Mapper &rhs) {
- marisa::swap(ptr_, rhs.ptr_);
- marisa::swap(avail_, rhs.avail_);
- marisa::swap(origin_, rhs.origin_);
- marisa::swap(size_, rhs.size_);
-#if (defined _WIN32) || (defined _WIN64)
- marisa::swap(file_, rhs.file_);
- marisa::swap(map_, rhs.map_);
-#else // (defined _WIN32) || (defined _WIN64)
- marisa::swap(fd_, rhs.fd_);
-#endif // (defined _WIN32) || (defined _WIN64)
-}
-
-const void *Mapper::map_data(std::size_t size) {
- MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
- MARISA_THROW_IF(size > avail_, MARISA_IO_ERROR);
-
- const char * const data = static_cast<const char *>(ptr_);
- ptr_ = data + size;
- avail_ -= size;
- return data;
-}
-
-#if (defined _WIN32) || (defined _WIN64)
- #ifdef __MSVCRT_VERSION__
- #if __MSVCRT_VERSION__ >= 0x0601
- #define MARISA_HAS_STAT64
- #endif // __MSVCRT_VERSION__ >= 0x0601
- #endif // __MSVCRT_VERSION__
-void Mapper::open_(const char *filename) {
- #ifdef MARISA_HAS_STAT64
- struct __stat64 st;
- MARISA_THROW_IF(::_stat64(filename, &st) != 0, MARISA_IO_ERROR);
- #else // MARISA_HAS_STAT64
- struct _stat st;
- MARISA_THROW_IF(::_stat(filename, &st) != 0, MARISA_IO_ERROR);
- #endif // MARISA_HAS_STAT64
- MARISA_THROW_IF((UInt64)st.st_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- size_ = (std::size_t)st.st_size;
-
- file_ = ::CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- MARISA_THROW_IF(file_ == INVALID_HANDLE_VALUE, MARISA_IO_ERROR);
-
- map_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY, 0, 0, NULL);
- MARISA_THROW_IF(map_ == NULL, MARISA_IO_ERROR);
-
- origin_ = ::MapViewOfFile(map_, FILE_MAP_READ, 0, 0, 0);
- MARISA_THROW_IF(origin_ == NULL, MARISA_IO_ERROR);
-
- ptr_ = static_cast<const char *>(origin_);
- avail_ = size_;
-}
-#else // (defined _WIN32) || (defined _WIN64)
-void Mapper::open_(const char *filename) {
- struct stat st;
- MARISA_THROW_IF(::stat(filename, &st) != 0, MARISA_IO_ERROR);
- MARISA_THROW_IF((UInt64)st.st_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- size_ = (std::size_t)st.st_size;
-
- fd_ = ::open(filename, O_RDONLY);
- MARISA_THROW_IF(fd_ == -1, MARISA_IO_ERROR);
-
- origin_ = ::mmap(NULL, size_, PROT_READ, MAP_SHARED, fd_, 0);
- MARISA_THROW_IF(origin_ == MAP_FAILED, MARISA_IO_ERROR);
-
- ptr_ = static_cast<const char *>(origin_);
- avail_ = size_;
-}
-#endif // (defined _WIN32) || (defined _WIN64)
-
-void Mapper::open_(const void *ptr, std::size_t size) {
- ptr_ = ptr;
- avail_ = size;
-}
-
-} // namespace io
-} // namespace grimoire
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_IO_MAPPER_H_
-#define MARISA_GRIMOIRE_IO_MAPPER_H_
-
-#include <cstdio>
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace io {
-
-class Mapper {
- public:
- Mapper();
- ~Mapper();
-
- void open(const char *filename);
- void open(const void *ptr, std::size_t size);
-
- template <typename T>
- void map(T *obj) {
- MARISA_THROW_IF(obj == NULL, MARISA_NULL_ERROR);
- *obj = *static_cast<const T *>(map_data(sizeof(T)));
- }
-
- template <typename T>
- void map(const T **objs, std::size_t num_objs) {
- MARISA_THROW_IF((objs == NULL) && (num_objs != 0), MARISA_NULL_ERROR);
- MARISA_THROW_IF(num_objs > (MARISA_SIZE_MAX / sizeof(T)),
- MARISA_SIZE_ERROR);
- *objs = static_cast<const T *>(map_data(sizeof(T) * num_objs));
- }
-
- void seek(std::size_t size);
-
- bool is_open() const;
-
- void clear();
- void swap(Mapper &rhs);
-
- private:
- const void *ptr_;
- void *origin_;
- std::size_t avail_;
- std::size_t size_;
-#if (defined _WIN32) || (defined _WIN64)
- void *file_;
- void *map_;
-#else // (defined _WIN32) || (defined _WIN64)
- int fd_;
-#endif // (defined _WIN32) || (defined _WIN64)
-
- void open_(const char *filename);
- void open_(const void *ptr, std::size_t size);
-
- const void *map_data(std::size_t size);
-
- // Disallows copy and assignment.
- Mapper(const Mapper &);
- Mapper &operator=(const Mapper &);
-};
-
-} // namespace io
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_IO_MAPPER_H_
+++ /dev/null
-#include <stdio.h>
-
-#ifdef _WIN32
- #include <io.h>
-#else // _WIN32
- #include <unistd.h>
-#endif // _WIN32
-
-#include <limits>
-
-#include "marisa/grimoire/io/reader.h"
-
-namespace marisa {
-namespace grimoire {
-namespace io {
-
-Reader::Reader()
- : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
-
-Reader::~Reader() {
- if (needs_fclose_) {
- ::fclose(file_);
- }
-}
-
-void Reader::open(const char *filename) {
- MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
-
- Reader temp;
- temp.open_(filename);
- swap(temp);
-}
-
-void Reader::open(std::FILE *file) {
- MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
-
- Reader temp;
- temp.open_(file);
- swap(temp);
-}
-
-void Reader::open(int fd) {
- MARISA_THROW_IF(fd == -1, MARISA_CODE_ERROR);
-
- Reader temp;
- temp.open_(fd);
- swap(temp);
-}
-
-void Reader::open(std::istream &stream) {
- Reader temp;
- temp.open_(stream);
- swap(temp);
-}
-
-void Reader::clear() {
- Reader().swap(*this);
-}
-
-void Reader::swap(Reader &rhs) {
- marisa::swap(file_, rhs.file_);
- marisa::swap(fd_, rhs.fd_);
- marisa::swap(stream_, rhs.stream_);
- marisa::swap(needs_fclose_, rhs.needs_fclose_);
-}
-
-void Reader::seek(std::size_t size) {
- MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
- if (size == 0) {
- return;
- } else if (size <= 16) {
- char buf[16];
- read_data(buf, size);
- } else {
- char buf[1024];
- while (size != 0) {
- const std::size_t count = (size < sizeof(buf)) ? size : sizeof(buf);
- read_data(buf, count);
- size -= count;
- }
- }
-}
-
-bool Reader::is_open() const {
- return (file_ != NULL) || (fd_ != -1) || (stream_ != NULL);
-}
-
-void Reader::open_(const char *filename) {
- std::FILE *file = NULL;
-#ifdef _MSC_VER
- MARISA_THROW_IF(::fopen_s(&file, filename, "rb") != 0, MARISA_IO_ERROR);
-#else // _MSC_VER
- file = ::fopen(filename, "rb");
- MARISA_THROW_IF(file == NULL, MARISA_IO_ERROR);
-#endif // _MSC_VER
- file_ = file;
- needs_fclose_ = true;
-}
-
-void Reader::open_(std::FILE *file) {
- file_ = file;
-}
-
-void Reader::open_(int fd) {
- fd_ = fd;
-}
-
-void Reader::open_(std::istream &stream) {
- stream_ = &stream;
-}
-
-void Reader::read_data(void *buf, std::size_t size) {
- MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
- if (size == 0) {
- return;
- } else if (fd_ != -1) {
- while (size != 0) {
-#ifdef _WIN32
- static const std::size_t CHUNK_SIZE =
- std::numeric_limits<int>::max();
- const unsigned int count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
- const int size_read = ::_read(fd_, buf, count);
-#else // _WIN32
- static const std::size_t CHUNK_SIZE =
- std::numeric_limits< ::ssize_t>::max();
- const ::size_t count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
- const ::ssize_t size_read = ::read(fd_, buf, count);
-#endif // _WIN32
- MARISA_THROW_IF(size_read <= 0, MARISA_IO_ERROR);
- buf = static_cast<char *>(buf) + size_read;
- size -= size_read;
- }
- } else if (file_ != NULL) {
- MARISA_THROW_IF(::fread(buf, 1, size, file_) != size, MARISA_IO_ERROR);
- } else if (stream_ != NULL) {
- try {
- MARISA_THROW_IF(!stream_->read(static_cast<char *>(buf), size),
- MARISA_IO_ERROR);
- } catch (const std::ios_base::failure &) {
- MARISA_THROW(MARISA_IO_ERROR, "std::ios_base::failure");
- }
- }
-}
-
-} // namespace io
-} // namespace grimoire
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_IO_READER_H_
-#define MARISA_GRIMOIRE_IO_READER_H_
-
-#include <cstdio>
-#include <iostream>
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace io {
-
-class Reader {
- public:
- Reader();
- ~Reader();
-
- void open(const char *filename);
- void open(std::FILE *file);
- void open(int fd);
- void open(std::istream &stream);
-
- template <typename T>
- void read(T *obj) {
- MARISA_THROW_IF(obj == NULL, MARISA_NULL_ERROR);
- read_data(obj, sizeof(T));
- }
-
- template <typename T>
- void read(T *objs, std::size_t num_objs) {
- MARISA_THROW_IF((objs == NULL) && (num_objs != 0), MARISA_NULL_ERROR);
- MARISA_THROW_IF(num_objs > (MARISA_SIZE_MAX / sizeof(T)),
- MARISA_SIZE_ERROR);
- read_data(objs, sizeof(T) * num_objs);
- }
-
- void seek(std::size_t size);
-
- bool is_open() const;
-
- void clear();
- void swap(Reader &rhs);
-
- private:
- std::FILE *file_;
- int fd_;
- std::istream *stream_;
- bool needs_fclose_;
-
- void open_(const char *filename);
- void open_(std::FILE *file);
- void open_(int fd);
- void open_(std::istream &stream);
-
- void read_data(void *buf, std::size_t size);
-
- // Disallows copy and assignment.
- Reader(const Reader &);
- Reader &operator=(const Reader &);
-};
-
-} // namespace io
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_IO_READER_H_
+++ /dev/null
-#include <stdio.h>
-
-#ifdef _WIN32
- #include <io.h>
-#else // _WIN32
- #include <unistd.h>
-#endif // _WIN32
-
-#include <limits>
-
-#include "marisa/grimoire/io/writer.h"
-
-namespace marisa {
-namespace grimoire {
-namespace io {
-
-Writer::Writer()
- : file_(NULL), fd_(-1), stream_(NULL), needs_fclose_(false) {}
-
-Writer::~Writer() {
- if (needs_fclose_) {
- ::fclose(file_);
- }
-}
-
-void Writer::open(const char *filename) {
- MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
-
- Writer temp;
- temp.open_(filename);
- swap(temp);
-}
-
-void Writer::open(std::FILE *file) {
- MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
-
- Writer temp;
- temp.open_(file);
- swap(temp);
-}
-
-void Writer::open(int fd) {
- MARISA_THROW_IF(fd == -1, MARISA_CODE_ERROR);
-
- Writer temp;
- temp.open_(fd);
- swap(temp);
-}
-
-void Writer::open(std::ostream &stream) {
- Writer temp;
- temp.open_(stream);
- swap(temp);
-}
-
-void Writer::clear() {
- Writer().swap(*this);
-}
-
-void Writer::swap(Writer &rhs) {
- marisa::swap(file_, rhs.file_);
- marisa::swap(fd_, rhs.fd_);
- marisa::swap(stream_, rhs.stream_);
- marisa::swap(needs_fclose_, rhs.needs_fclose_);
-}
-
-void Writer::seek(std::size_t size) {
- MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
- if (size == 0) {
- return;
- } else if (size <= 16) {
- const char buf[16] = {};
- write_data(buf, size);
- } else {
- const char buf[1024] = {};
- do {
- const std::size_t count = (size < sizeof(buf)) ? size : sizeof(buf);
- write_data(buf, count);
- size -= count;
- } while (size != 0);
- }
-}
-
-bool Writer::is_open() const {
- return (file_ != NULL) || (fd_ != -1) || (stream_ != NULL);
-}
-
-void Writer::open_(const char *filename) {
- std::FILE *file = NULL;
-#ifdef _MSC_VER
- MARISA_THROW_IF(::fopen_s(&file, filename, "wb") != 0, MARISA_IO_ERROR);
-#else // _MSC_VER
- file = ::fopen(filename, "wb");
- MARISA_THROW_IF(file == NULL, MARISA_IO_ERROR);
-#endif // _MSC_VER
- file_ = file;
- needs_fclose_ = true;
-}
-
-void Writer::open_(std::FILE *file) {
- file_ = file;
-}
-
-void Writer::open_(int fd) {
- fd_ = fd;
-}
-
-void Writer::open_(std::ostream &stream) {
- stream_ = &stream;
-}
-
-void Writer::write_data(const void *data, std::size_t size) {
- MARISA_THROW_IF(!is_open(), MARISA_STATE_ERROR);
- if (size == 0) {
- return;
- } else if (fd_ != -1) {
- while (size != 0) {
-#ifdef _WIN32
- static const std::size_t CHUNK_SIZE =
- std::numeric_limits<int>::max();
- const unsigned int count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
- const int size_written = ::_write(fd_, data, count);
-#else // _WIN32
- static const std::size_t CHUNK_SIZE =
- std::numeric_limits< ::ssize_t>::max();
- const ::size_t count = (size < CHUNK_SIZE) ? size : CHUNK_SIZE;
- const ::ssize_t size_written = ::write(fd_, data, count);
-#endif // _WIN32
- MARISA_THROW_IF(size_written <= 0, MARISA_IO_ERROR);
- data = static_cast<const char *>(data) + size_written;
- size -= size_written;
- }
- } else if (file_ != NULL) {
- MARISA_THROW_IF(::fwrite(data, 1, size, file_) != size, MARISA_IO_ERROR);
- MARISA_THROW_IF(::fflush(file_) != 0, MARISA_IO_ERROR);
- } else if (stream_ != NULL) {
- try {
- MARISA_THROW_IF(!stream_->write(static_cast<const char *>(data), size),
- MARISA_IO_ERROR);
- } catch (const std::ios_base::failure &) {
- MARISA_THROW(MARISA_IO_ERROR, "std::ios_base::failure");
- }
- }
-}
-
-} // namespace io
-} // namespace grimoire
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_IO_WRITER_H_
-#define MARISA_GRIMOIRE_IO_WRITER_H_
-
-#include <cstdio>
-#include <iostream>
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace io {
-
-class Writer {
- public:
- Writer();
- ~Writer();
-
- void open(const char *filename);
- void open(std::FILE *file);
- void open(int fd);
- void open(std::ostream &stream);
-
- template <typename T>
- void write(const T &obj) {
- write_data(&obj, sizeof(T));
- }
-
- template <typename T>
- void write(const T *objs, std::size_t num_objs) {
- MARISA_THROW_IF((objs == NULL) && (num_objs != 0), MARISA_NULL_ERROR);
- MARISA_THROW_IF(num_objs > (MARISA_SIZE_MAX / sizeof(T)),
- MARISA_SIZE_ERROR);
- write_data(objs, sizeof(T) * num_objs);
- }
-
- void seek(std::size_t size);
-
- bool is_open() const;
-
- void clear();
- void swap(Writer &rhs);
-
- private:
- std::FILE *file_;
- int fd_;
- std::ostream *stream_;
- bool needs_fclose_;
-
- void open_(const char *filename);
- void open_(std::FILE *file);
- void open_(int fd);
- void open_(std::ostream &stream);
-
- void write_data(const void *data, std::size_t size);
-
- // Disallows copy and assignment.
- Writer(const Writer &);
- Writer &operator=(const Writer &);
-};
-
-} // namespace io
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_IO_WRITER_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_H_
-#define MARISA_GRIMOIRE_TRIE_H_
-
-#include "marisa/grimoire/trie/state.h"
-#include "marisa/grimoire/trie/louds-trie.h"
-
-namespace marisa {
-namespace grimoire {
-
-using trie::State;
-using trie::LoudsTrie;
-
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_CACHE_H_
-#define MARISA_GRIMOIRE_TRIE_CACHE_H_
-
-#include <cfloat>
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Cache {
- public:
- Cache() : parent_(0), child_(0), union_() {
- union_.weight = FLT_MIN;
- }
- Cache(const Cache &cache)
- : parent_(cache.parent_), child_(cache.child_), union_(cache.union_) {}
-
- Cache &operator=(const Cache &cache) {
- parent_ = cache.parent_;
- child_ = cache.child_;
- union_ = cache.union_;
- return *this;
- }
-
- void set_parent(std::size_t parent) {
- MARISA_DEBUG_IF(parent > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- parent_ = (UInt32)parent;
- }
- void set_child(std::size_t child) {
- MARISA_DEBUG_IF(child > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- child_ = (UInt32)child;
- }
- void set_base(UInt8 base) {
- union_.link = (union_.link & ~0xFFU) | base;
- }
- void set_extra(std::size_t extra) {
- MARISA_DEBUG_IF(extra > (MARISA_UINT32_MAX >> 8), MARISA_SIZE_ERROR);
- union_.link = (UInt32)((union_.link & 0xFFU) | (extra << 8));
- }
- void set_weight(float weight) {
- union_.weight = weight;
- }
-
- std::size_t parent() const {
- return parent_;
- }
- std::size_t child() const {
- return child_;
- }
- UInt8 base() const {
- return (UInt8)(union_.link & 0xFFU);
- }
- std::size_t extra() const {
- return union_.link >> 8;
- }
- char label() const {
- return (char)base();
- }
- std::size_t link() const {
- return union_.link;
- }
- float weight() const {
- return union_.weight;
- }
-
- private:
- UInt32 parent_;
- UInt32 child_;
- union Union {
- UInt32 link;
- float weight;
- } union_;
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_CACHE_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_CONFIG_H_
-#define MARISA_GRIMOIRE_TRIE_CONFIG_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Config {
- public:
- Config()
- : num_tries_(MARISA_DEFAULT_NUM_TRIES),
- cache_level_(MARISA_DEFAULT_CACHE),
- tail_mode_(MARISA_DEFAULT_TAIL),
- node_order_(MARISA_DEFAULT_ORDER) {}
-
- void parse(int config_flags) {
- Config temp;
- temp.parse_(config_flags);
- swap(temp);
- }
-
- int flags() const {
- return (int)num_tries_ | tail_mode_ | node_order_;
- }
-
- std::size_t num_tries() const {
- return num_tries_;
- }
- CacheLevel cache_level() const {
- return cache_level_;
- }
- TailMode tail_mode() const {
- return tail_mode_;
- }
- NodeOrder node_order() const {
- return node_order_;
- }
-
- void clear() {
- Config().swap(*this);
- }
- void swap(Config &rhs) {
- marisa::swap(num_tries_, rhs.num_tries_);
- marisa::swap(cache_level_, rhs.cache_level_);
- marisa::swap(tail_mode_, rhs.tail_mode_);
- marisa::swap(node_order_, rhs.node_order_);
- }
-
- private:
- std::size_t num_tries_;
- CacheLevel cache_level_;
- TailMode tail_mode_;
- NodeOrder node_order_;
-
- void parse_(int config_flags) {
- MARISA_THROW_IF((config_flags & ~MARISA_CONFIG_MASK) != 0,
- MARISA_CODE_ERROR);
-
- parse_num_tries(config_flags);
- parse_cache_level(config_flags);
- parse_tail_mode(config_flags);
- parse_node_order(config_flags);
- }
-
- void parse_num_tries(int config_flags) {
- const int num_tries = config_flags & MARISA_NUM_TRIES_MASK;
- if (num_tries != 0) {
- num_tries_ = num_tries;
- }
- }
-
- void parse_cache_level(int config_flags) {
- switch (config_flags & MARISA_CACHE_LEVEL_MASK) {
- case 0: {
- cache_level_ = MARISA_DEFAULT_CACHE;
- break;
- }
- case MARISA_HUGE_CACHE: {
- cache_level_ = MARISA_HUGE_CACHE;
- break;
- }
- case MARISA_LARGE_CACHE: {
- cache_level_ = MARISA_LARGE_CACHE;
- break;
- }
- case MARISA_NORMAL_CACHE: {
- cache_level_ = MARISA_NORMAL_CACHE;
- break;
- }
- case MARISA_SMALL_CACHE: {
- cache_level_ = MARISA_SMALL_CACHE;
- break;
- }
- case MARISA_TINY_CACHE: {
- cache_level_ = MARISA_TINY_CACHE;
- break;
- }
- default: {
- MARISA_THROW(MARISA_CODE_ERROR, "undefined cache level");
- }
- }
- }
-
- void parse_tail_mode(int config_flags) {
- switch (config_flags & MARISA_TAIL_MODE_MASK) {
- case 0: {
- tail_mode_ = MARISA_DEFAULT_TAIL;
- break;
- }
- case MARISA_TEXT_TAIL: {
- tail_mode_ = MARISA_TEXT_TAIL;
- break;
- }
- case MARISA_BINARY_TAIL: {
- tail_mode_ = MARISA_BINARY_TAIL;
- break;
- }
- default: {
- MARISA_THROW(MARISA_CODE_ERROR, "undefined tail mode");
- }
- }
- }
-
- void parse_node_order(int config_flags) {
- switch (config_flags & MARISA_NODE_ORDER_MASK) {
- case 0: {
- node_order_ = MARISA_DEFAULT_ORDER;
- break;
- }
- case MARISA_LABEL_ORDER: {
- node_order_ = MARISA_LABEL_ORDER;
- break;
- }
- case MARISA_WEIGHT_ORDER: {
- node_order_ = MARISA_WEIGHT_ORDER;
- break;
- }
- default: {
- MARISA_THROW(MARISA_CODE_ERROR, "undefined node order");
- }
- }
- }
-
- // Disallows copy and assignment.
- Config(const Config &);
- Config &operator=(const Config &);
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_CONFIG_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_ENTRY_H_
-#define MARISA_GRIMOIRE_TRIE_ENTRY_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Entry {
- public:
- Entry()
- : ptr_(static_cast<const char *>(NULL) - 1), length_(0), id_(0) {}
- Entry(const Entry &entry)
- : ptr_(entry.ptr_), length_(entry.length_), id_(entry.id_) {}
-
- Entry &operator=(const Entry &entry) {
- ptr_ = entry.ptr_;
- length_ = entry.length_;
- id_ = entry.id_;
- return *this;
- }
-
- char operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= length_, MARISA_BOUND_ERROR);
- return *(ptr_ - i);
- }
-
- void set_str(const char *ptr, std::size_t length) {
- MARISA_DEBUG_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- MARISA_DEBUG_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- ptr_ = ptr + length - 1;
- length_ = (UInt32)length;
- }
- void set_id(std::size_t id) {
- MARISA_DEBUG_IF(id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- id_ = (UInt32)id;
- }
-
- const char *ptr() const {
- return ptr_ - length_ + 1;
- }
- std::size_t length() const {
- return length_;
- }
- std::size_t id() const {
- return id_;
- }
-
- class StringComparer {
- public:
- bool operator()(const Entry &lhs, const Entry &rhs) const {
- for (std::size_t i = 0; i < lhs.length(); ++i) {
- if (i == rhs.length()) {
- return true;
- }
- if (lhs[i] != rhs[i]) {
- return (UInt8)lhs[i] > (UInt8)rhs[i];
- }
- }
- return lhs.length() > rhs.length();
- }
- };
-
- class IDComparer {
- public:
- bool operator()(const Entry &lhs, const Entry &rhs) const {
- return lhs.id_ < rhs.id_;
- }
- };
-
- private:
- const char *ptr_;
- UInt32 length_;
- UInt32 id_;
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_ENTRY_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_HEADER_H_
-#define MARISA_GRIMOIRE_TRIE_HEADER_H_
-
-#include "marisa/grimoire/io.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Header {
- public:
- enum {
- HEADER_SIZE = 16
- };
-
- Header() {}
-
- void map(Mapper &mapper) {
- const char *ptr;
- mapper.map(&ptr, HEADER_SIZE);
- MARISA_THROW_IF(!test_header(ptr), MARISA_FORMAT_ERROR);
- }
- void read(Reader &reader) {
- char buf[HEADER_SIZE];
- reader.read(buf, HEADER_SIZE);
- MARISA_THROW_IF(!test_header(buf), MARISA_FORMAT_ERROR);
- }
- void write(Writer &writer) const {
- writer.write(get_header(), HEADER_SIZE);
- }
-
- std::size_t io_size() const {
- return HEADER_SIZE;
- }
-
- private:
-
- static const char *get_header() {
- static const char buf[HEADER_SIZE] = "We love Marisa.";
- return buf;
- }
-
- static bool test_header(const char *ptr) {
- for (std::size_t i = 0; i < HEADER_SIZE; ++i) {
- if (ptr[i] != get_header()[i]) {
- return false;
- }
- }
- return true;
- }
-
- // Disallows copy and assignment.
- Header(const Header &);
- Header &operator=(const Header &);
-};
-
-} // namespace trie
-} // namespace marisa
-} // namespace grimoire
-
-#endif // MARISA_GRIMOIRE_TRIE_HEADER_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_STATE_HISTORY_H_
-#define MARISA_GRIMOIRE_TRIE_STATE_HISTORY_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class History {
- public:
- History()
- : node_id_(0), louds_pos_(0), key_pos_(0),
- link_id_(MARISA_INVALID_LINK_ID), key_id_(MARISA_INVALID_KEY_ID) {}
-
- void set_node_id(std::size_t node_id) {
- MARISA_DEBUG_IF(node_id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- node_id_ = (UInt32)node_id;
- }
- void set_louds_pos(std::size_t louds_pos) {
- MARISA_DEBUG_IF(louds_pos > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- louds_pos_ = (UInt32)louds_pos;
- }
- void set_key_pos(std::size_t key_pos) {
- MARISA_DEBUG_IF(key_pos > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- key_pos_ = (UInt32)key_pos;
- }
- void set_link_id(std::size_t link_id) {
- MARISA_DEBUG_IF(link_id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- link_id_ = (UInt32)link_id;
- }
- void set_key_id(std::size_t key_id) {
- MARISA_DEBUG_IF(key_id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- key_id_ = (UInt32)key_id;
- }
-
- std::size_t node_id() const {
- return node_id_;
- }
- std::size_t louds_pos() const {
- return louds_pos_;
- }
- std::size_t key_pos() const {
- return key_pos_;
- }
- std::size_t link_id() const {
- return link_id_;
- }
- std::size_t key_id() const {
- return key_id_;
- }
-
- private:
- UInt32 node_id_;
- UInt32 louds_pos_;
- UInt32 key_pos_;
- UInt32 link_id_;
- UInt32 key_id_;
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_STATE_HISTORY_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_KEY_H_
-#define MARISA_GRIMOIRE_TRIE_KEY_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Key {
- public:
- Key() : ptr_(NULL), length_(0), union_(), id_(0) {
- union_.terminal = 0;
- }
- Key(const Key &entry)
- : ptr_(entry.ptr_), length_(entry.length_),
- union_(entry.union_), id_(entry.id_) {}
-
- Key &operator=(const Key &entry) {
- ptr_ = entry.ptr_;
- length_ = entry.length_;
- union_ = entry.union_;
- id_ = entry.id_;
- return *this;
- }
-
- char operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= length_, MARISA_BOUND_ERROR);
- return ptr_[i];
- }
-
- void substr(std::size_t pos, std::size_t length) {
- MARISA_DEBUG_IF(pos > length_, MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(length > length_, MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(pos > (length_ - length), MARISA_BOUND_ERROR);
- ptr_ += pos;
- length_ = (UInt32)length;
- }
-
- void set_str(const char *ptr, std::size_t length) {
- MARISA_DEBUG_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- MARISA_DEBUG_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- ptr_ = ptr;
- length_ = (UInt32)length;
- }
- void set_weight(float weight) {
- union_.weight = weight;
- }
- void set_terminal(std::size_t terminal) {
- MARISA_DEBUG_IF(terminal > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- union_.terminal = (UInt32)terminal;
- }
- void set_id(std::size_t id) {
- MARISA_DEBUG_IF(id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- id_ = (UInt32)id;
- }
-
- const char *ptr() const {
- return ptr_;
- }
- std::size_t length() const {
- return length_;
- }
- float weight() const {
- return union_.weight;
- }
- std::size_t terminal() const {
- return union_.terminal;
- }
- std::size_t id() const {
- return id_;
- }
-
- private:
- const char *ptr_;
- UInt32 length_;
- union Union {
- float weight;
- UInt32 terminal;
- } union_;
- UInt32 id_;
-};
-
-inline bool operator==(const Key &lhs, const Key &rhs) {
- if (lhs.length() != rhs.length()) {
- return false;
- }
- for (std::size_t i = 0; i < lhs.length(); ++i) {
- if (lhs[i] != rhs[i]) {
- return false;
- }
- }
- return true;
-}
-
-inline bool operator!=(const Key &lhs, const Key &rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator<(const Key &lhs, const Key &rhs) {
- for (std::size_t i = 0; i < lhs.length(); ++i) {
- if (i == rhs.length()) {
- return false;
- }
- if (lhs[i] != rhs[i]) {
- return (UInt8)lhs[i] < (UInt8)rhs[i];
- }
- }
- return lhs.length() < rhs.length();
-}
-
-inline bool operator>(const Key &lhs, const Key &rhs) {
- return rhs < lhs;
-}
-
-class ReverseKey {
- public:
- ReverseKey() : ptr_(NULL), length_(0), union_(), id_(0) {
- union_.terminal = 0;
- }
- ReverseKey(const ReverseKey &entry)
- : ptr_(entry.ptr_), length_(entry.length_),
- union_(entry.union_), id_(entry.id_) {}
-
- ReverseKey &operator=(const ReverseKey &entry) {
- ptr_ = entry.ptr_;
- length_ = entry.length_;
- union_ = entry.union_;
- id_ = entry.id_;
- return *this;
- }
-
- char operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= length_, MARISA_BOUND_ERROR);
- return *(ptr_ - i - 1);
- }
-
- void substr(std::size_t pos, std::size_t length) {
- MARISA_DEBUG_IF(pos > length_, MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(length > length_, MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(pos > (length_ - length), MARISA_BOUND_ERROR);
- ptr_ -= pos;
- length_ = (UInt32)length;
- }
-
- void set_str(const char *ptr, std::size_t length) {
- MARISA_DEBUG_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- MARISA_DEBUG_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- ptr_ = ptr + length;
- length_ = (UInt32)length;
- }
- void set_weight(float weight) {
- union_.weight = weight;
- }
- void set_terminal(std::size_t terminal) {
- MARISA_DEBUG_IF(terminal > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- union_.terminal = (UInt32)terminal;
- }
- void set_id(std::size_t id) {
- MARISA_DEBUG_IF(id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- id_ = (UInt32)id;
- }
-
- const char *ptr() const {
- return ptr_ - length_;
- }
- std::size_t length() const {
- return length_;
- }
- float weight() const {
- return union_.weight;
- }
- std::size_t terminal() const {
- return union_.terminal;
- }
- std::size_t id() const {
- return id_;
- }
-
- private:
- const char *ptr_;
- UInt32 length_;
- union Union {
- float weight;
- UInt32 terminal;
- } union_;
- UInt32 id_;
-};
-
-inline bool operator==(const ReverseKey &lhs, const ReverseKey &rhs) {
- if (lhs.length() != rhs.length()) {
- return false;
- }
- for (std::size_t i = 0; i < lhs.length(); ++i) {
- if (lhs[i] != rhs[i]) {
- return false;
- }
- }
- return true;
-}
-
-inline bool operator!=(const ReverseKey &lhs, const ReverseKey &rhs) {
- return !(lhs == rhs);
-}
-
-inline bool operator<(const ReverseKey &lhs, const ReverseKey &rhs) {
- for (std::size_t i = 0; i < lhs.length(); ++i) {
- if (i == rhs.length()) {
- return false;
- }
- if (lhs[i] != rhs[i]) {
- return (UInt8)lhs[i] < (UInt8)rhs[i];
- }
- }
- return lhs.length() < rhs.length();
-}
-
-inline bool operator>(const ReverseKey &lhs, const ReverseKey &rhs) {
- return rhs < lhs;
-}
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_KEY_H_
+++ /dev/null
-#include <algorithm>
-#include <functional>
-#include <queue>
-
-#include "marisa/grimoire/algorithm.h"
-#include "marisa/grimoire/trie/header.h"
-#include "marisa/grimoire/trie/range.h"
-#include "marisa/grimoire/trie/state.h"
-#include "marisa/grimoire/trie/louds-trie.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-LoudsTrie::LoudsTrie()
- : louds_(), terminal_flags_(), link_flags_(), bases_(), extras_(),
- tail_(), next_trie_(), cache_(), cache_mask_(0), num_l1_nodes_(0),
- config_(), mapper_() {}
-
-LoudsTrie::~LoudsTrie() {}
-
-void LoudsTrie::build(Keyset &keyset, int flags) {
- Config config;
- config.parse(flags);
-
- LoudsTrie temp;
- temp.build_(keyset, config);
- swap(temp);
-}
-
-void LoudsTrie::map(Mapper &mapper) {
- Header().map(mapper);
-
- LoudsTrie temp;
- temp.map_(mapper);
- temp.mapper_.swap(mapper);
- swap(temp);
-}
-
-void LoudsTrie::read(Reader &reader) {
- Header().read(reader);
-
- LoudsTrie temp;
- temp.read_(reader);
- swap(temp);
-}
-
-void LoudsTrie::write(Writer &writer) const {
- Header().write(writer);
-
- write_(writer);
-}
-
-bool LoudsTrie::lookup(Agent &agent) const {
- MARISA_DEBUG_IF(!agent.has_state(), MARISA_STATE_ERROR);
-
- State &state = agent.state();
- state.lookup_init();
- while (state.query_pos() < agent.query().length()) {
- if (!find_child(agent)) {
- return false;
- }
- }
- if (!terminal_flags_[state.node_id()]) {
- return false;
- }
- agent.set_key(agent.query().ptr(), agent.query().length());
- agent.set_key(terminal_flags_.rank1(state.node_id()));
- return true;
-}
-
-void LoudsTrie::reverse_lookup(Agent &agent) const {
- MARISA_DEBUG_IF(!agent.has_state(), MARISA_STATE_ERROR);
- MARISA_THROW_IF(agent.query().id() >= size(), MARISA_BOUND_ERROR);
-
- State &state = agent.state();
- state.reverse_lookup_init();
-
- state.set_node_id(terminal_flags_.select1(agent.query().id()));
- if (state.node_id() == 0) {
- agent.set_key(state.key_buf().begin(), state.key_buf().size());
- agent.set_key(agent.query().id());
- return;
- }
- for ( ; ; ) {
- if (link_flags_[state.node_id()]) {
- const std::size_t prev_key_pos = state.key_buf().size();
- restore(agent, get_link(state.node_id()));
- std::reverse(state.key_buf().begin() + prev_key_pos,
- state.key_buf().end());
- } else {
- state.key_buf().push_back((char)bases_[state.node_id()]);
- }
-
- if (state.node_id() <= num_l1_nodes_) {
- std::reverse(state.key_buf().begin(), state.key_buf().end());
- agent.set_key(state.key_buf().begin(), state.key_buf().size());
- agent.set_key(agent.query().id());
- return;
- }
- state.set_node_id(louds_.select1(state.node_id()) - state.node_id() - 1);
- }
-}
-
-bool LoudsTrie::common_prefix_search(Agent &agent) const {
- MARISA_DEBUG_IF(!agent.has_state(), MARISA_STATE_ERROR);
-
- State &state = agent.state();
- if (state.status_code() == MARISA_END_OF_COMMON_PREFIX_SEARCH) {
- return false;
- }
-
- if (state.status_code() != MARISA_READY_TO_COMMON_PREFIX_SEARCH) {
- state.common_prefix_search_init();
- if (terminal_flags_[state.node_id()]) {
- agent.set_key(agent.query().ptr(), state.query_pos());
- agent.set_key(terminal_flags_.rank1(state.node_id()));
- return true;
- }
- }
-
- while (state.query_pos() < agent.query().length()) {
- if (!find_child(agent)) {
- state.set_status_code(MARISA_END_OF_COMMON_PREFIX_SEARCH);
- return false;
- } else if (terminal_flags_[state.node_id()]) {
- agent.set_key(agent.query().ptr(), state.query_pos());
- agent.set_key(terminal_flags_.rank1(state.node_id()));
- return true;
- }
- }
- state.set_status_code(MARISA_END_OF_COMMON_PREFIX_SEARCH);
- return false;
-}
-
-bool LoudsTrie::predictive_search(Agent &agent) const {
- MARISA_DEBUG_IF(!agent.has_state(), MARISA_STATE_ERROR);
-
- State &state = agent.state();
- if (state.status_code() == MARISA_END_OF_PREDICTIVE_SEARCH) {
- return false;
- }
-
- if (state.status_code() != MARISA_READY_TO_PREDICTIVE_SEARCH) {
- state.predictive_search_init();
- while (state.query_pos() < agent.query().length()) {
- if (!predictive_find_child(agent)) {
- state.set_status_code(MARISA_END_OF_PREDICTIVE_SEARCH);
- return false;
- }
- }
-
- History history;
- history.set_node_id(state.node_id());
- history.set_key_pos(state.key_buf().size());
- state.history().push_back(history);
- state.set_history_pos(1);
-
- if (terminal_flags_[state.node_id()]) {
- agent.set_key(state.key_buf().begin(), state.key_buf().size());
- agent.set_key(terminal_flags_.rank1(state.node_id()));
- return true;
- }
- }
-
- for ( ; ; ) {
- if (state.history_pos() == state.history().size()) {
- const History ¤t = state.history().back();
- History next;
- next.set_louds_pos(louds_.select0(current.node_id()) + 1);
- next.set_node_id(next.louds_pos() - current.node_id() - 1);
- state.history().push_back(next);
- }
-
- History &next = state.history()[state.history_pos()];
- const bool link_flag = louds_[next.louds_pos()];
- next.set_louds_pos(next.louds_pos() + 1);
- if (link_flag) {
- state.set_history_pos(state.history_pos() + 1);
- if (link_flags_[next.node_id()]) {
- next.set_link_id(update_link_id(next.link_id(), next.node_id()));
- restore(agent, get_link(next.node_id(), next.link_id()));
- } else {
- state.key_buf().push_back((char)bases_[next.node_id()]);
- }
- next.set_key_pos(state.key_buf().size());
-
- if (terminal_flags_[next.node_id()]) {
- if (next.key_id() == MARISA_INVALID_KEY_ID) {
- next.set_key_id(terminal_flags_.rank1(next.node_id()));
- } else {
- next.set_key_id(next.key_id() + 1);
- }
- agent.set_key(state.key_buf().begin(), state.key_buf().size());
- agent.set_key(next.key_id());
- return true;
- }
- } else if (state.history_pos() != 1) {
- History ¤t = state.history()[state.history_pos() - 1];
- current.set_node_id(current.node_id() + 1);
- const History &prev =
- state.history()[state.history_pos() - 2];
- state.key_buf().resize(prev.key_pos());
- state.set_history_pos(state.history_pos() - 1);
- } else {
- state.set_status_code(MARISA_END_OF_PREDICTIVE_SEARCH);
- return false;
- }
- }
-}
-
-std::size_t LoudsTrie::total_size() const {
- return louds_.total_size() + terminal_flags_.total_size()
- + link_flags_.total_size() + bases_.total_size()
- + extras_.total_size() + tail_.total_size()
- + ((next_trie_.get() != NULL) ? next_trie_->total_size() : 0)
- + cache_.total_size();
-}
-
-std::size_t LoudsTrie::io_size() const {
- return Header().io_size() + louds_.io_size()
- + terminal_flags_.io_size() + link_flags_.io_size()
- + bases_.io_size() + extras_.io_size() + tail_.io_size()
- + ((next_trie_.get() != NULL) ?
- (next_trie_->io_size() - Header().io_size()) : 0)
- + cache_.io_size() + (sizeof(UInt32) * 2);
-}
-
-void LoudsTrie::clear() {
- LoudsTrie().swap(*this);
-}
-
-void LoudsTrie::swap(LoudsTrie &rhs) {
- louds_.swap(rhs.louds_);
- terminal_flags_.swap(rhs.terminal_flags_);
- link_flags_.swap(rhs.link_flags_);
- bases_.swap(rhs.bases_);
- extras_.swap(rhs.extras_);
- tail_.swap(rhs.tail_);
- next_trie_.swap(rhs.next_trie_);
- cache_.swap(rhs.cache_);
- marisa::swap(cache_mask_, rhs.cache_mask_);
- marisa::swap(num_l1_nodes_, rhs.num_l1_nodes_);
- config_.swap(rhs.config_);
- mapper_.swap(rhs.mapper_);
-}
-
-void LoudsTrie::build_(Keyset &keyset, const Config &config) {
- Vector<Key> keys;
- keys.resize(keyset.size());
- for (std::size_t i = 0; i < keyset.size(); ++i) {
- keys[i].set_str(keyset[i].ptr(), keyset[i].length());
- keys[i].set_weight(keyset[i].weight());
- }
-
- Vector<UInt32> terminals;
- build_trie(keys, &terminals, config, 1);
-
- typedef std::pair<UInt32, UInt32> TerminalIdPair;
-
- Vector<TerminalIdPair> pairs;
- pairs.resize(terminals.size());
- for (std::size_t i = 0; i < pairs.size(); ++i) {
- pairs[i].first = terminals[i];
- pairs[i].second = (UInt32)i;
- }
- terminals.clear();
- std::sort(pairs.begin(), pairs.end());
-
- std::size_t node_id = 0;
- for (std::size_t i = 0; i < pairs.size(); ++i) {
- while (node_id < pairs[i].first) {
- terminal_flags_.push_back(false);
- ++node_id;
- }
- if (node_id == pairs[i].first) {
- terminal_flags_.push_back(true);
- ++node_id;
- }
- }
- while (node_id < bases_.size()) {
- terminal_flags_.push_back(false);
- ++node_id;
- }
- terminal_flags_.push_back(false);
- terminal_flags_.build(false, true);
-
- for (std::size_t i = 0; i < keyset.size(); ++i) {
- keyset[pairs[i].second].set_id(terminal_flags_.rank1(pairs[i].first));
- }
-}
-
-template <typename T>
-void LoudsTrie::build_trie(Vector<T> &keys,
- Vector<UInt32> *terminals, const Config &config, std::size_t trie_id) {
- build_current_trie(keys, terminals, config, trie_id);
-
- Vector<UInt32> next_terminals;
- if (!keys.empty()) {
- build_next_trie(keys, &next_terminals, config, trie_id);
- }
-
- if (next_trie_.get() != NULL) {
- config_.parse(static_cast<int>((next_trie_->num_tries() + 1)) |
- next_trie_->tail_mode() | next_trie_->node_order());
- } else {
- config_.parse(1 | tail_.mode() | config.node_order() |
- config.cache_level());
- }
-
- link_flags_.build(false, false);
- std::size_t node_id = 0;
- for (std::size_t i = 0; i < next_terminals.size(); ++i) {
- while (!link_flags_[node_id]) {
- ++node_id;
- }
- bases_[node_id] = (UInt8)(next_terminals[i] % 256);
- next_terminals[i] /= 256;
- ++node_id;
- }
- extras_.build(next_terminals);
- fill_cache();
-}
-
-template <typename T>
-void LoudsTrie::build_current_trie(Vector<T> &keys,
- Vector<UInt32> *terminals, const Config &config,
- std::size_t trie_id) try {
- for (std::size_t i = 0; i < keys.size(); ++i) {
- keys[i].set_id(i);
- }
- const std::size_t num_keys = Algorithm().sort(keys.begin(), keys.end());
- reserve_cache(config, trie_id, num_keys);
-
- louds_.push_back(true);
- louds_.push_back(false);
- bases_.push_back('\0');
- link_flags_.push_back(false);
-
- Vector<T> next_keys;
- std::queue<Range> queue;
- Vector<WeightedRange> w_ranges;
-
- queue.push(make_range(0, keys.size(), 0));
- while (!queue.empty()) {
- const std::size_t node_id = link_flags_.size() - queue.size();
-
- Range range = queue.front();
- queue.pop();
-
- while ((range.begin() < range.end()) &&
- (keys[range.begin()].length() == range.key_pos())) {
- keys[range.begin()].set_terminal(node_id);
- range.set_begin(range.begin() + 1);
- }
-
- if (range.begin() == range.end()) {
- louds_.push_back(false);
- continue;
- }
-
- w_ranges.clear();
- double weight = keys[range.begin()].weight();
- for (std::size_t i = range.begin() + 1; i < range.end(); ++i) {
- if (keys[i - 1][range.key_pos()] != keys[i][range.key_pos()]) {
- w_ranges.push_back(make_weighted_range(
- range.begin(), i, range.key_pos(), (float)weight));
- range.set_begin(i);
- weight = 0.0;
- }
- weight += keys[i].weight();
- }
- w_ranges.push_back(make_weighted_range(
- range.begin(), range.end(), range.key_pos(), (float)weight));
- if (config.node_order() == MARISA_WEIGHT_ORDER) {
- std::stable_sort(w_ranges.begin(), w_ranges.end(),
- std::greater<WeightedRange>());
- }
-
- if (node_id == 0) {
- num_l1_nodes_ = w_ranges.size();
- }
-
- for (std::size_t i = 0; i < w_ranges.size(); ++i) {
- WeightedRange &w_range = w_ranges[i];
- std::size_t key_pos = w_range.key_pos() + 1;
- while (key_pos < keys[w_range.begin()].length()) {
- std::size_t j;
- for (j = w_range.begin() + 1; j < w_range.end(); ++j) {
- if (keys[j - 1][key_pos] != keys[j][key_pos]) {
- break;
- }
- }
- if (j < w_range.end()) {
- break;
- }
- ++key_pos;
- }
- cache<T>(node_id, bases_.size(), w_range.weight(),
- keys[w_range.begin()][w_range.key_pos()]);
-
- if (key_pos == w_range.key_pos() + 1) {
- bases_.push_back(keys[w_range.begin()][w_range.key_pos()]);
- link_flags_.push_back(false);
- } else {
- bases_.push_back('\0');
- link_flags_.push_back(true);
- T next_key;
- next_key.set_str(keys[w_range.begin()].ptr(),
- keys[w_range.begin()].length());
- next_key.substr(w_range.key_pos(), key_pos - w_range.key_pos());
- next_key.set_weight(w_range.weight());
- next_keys.push_back(next_key);
- }
- w_range.set_key_pos(key_pos);
- queue.push(w_range.range());
- louds_.push_back(true);
- }
- louds_.push_back(false);
- }
-
- louds_.push_back(false);
- louds_.build(trie_id == 1, true);
- bases_.shrink();
-
- build_terminals(keys, terminals);
- keys.swap(next_keys);
-} catch (const std::bad_alloc &) {
- MARISA_THROW(MARISA_MEMORY_ERROR, "std::bad_alloc");
-}
-
-template <>
-void LoudsTrie::build_next_trie(Vector<Key> &keys,
- Vector<UInt32> *terminals, const Config &config, std::size_t trie_id) {
- if (trie_id == config.num_tries()) {
- Vector<Entry> entries;
- entries.resize(keys.size());
- for (std::size_t i = 0; i < keys.size(); ++i) {
- entries[i].set_str(keys[i].ptr(), keys[i].length());
- }
- tail_.build(entries, terminals, config.tail_mode());
- return;
- }
- Vector<ReverseKey> reverse_keys;
- reverse_keys.resize(keys.size());
- for (std::size_t i = 0; i < keys.size(); ++i) {
- reverse_keys[i].set_str(keys[i].ptr(), keys[i].length());
- reverse_keys[i].set_weight(keys[i].weight());
- }
- keys.clear();
- next_trie_.reset(new (std::nothrow) LoudsTrie);
- MARISA_THROW_IF(next_trie_.get() == NULL, MARISA_MEMORY_ERROR);
- next_trie_->build_trie(reverse_keys, terminals, config, trie_id + 1);
-}
-
-template <>
-void LoudsTrie::build_next_trie(Vector<ReverseKey> &keys,
- Vector<UInt32> *terminals, const Config &config, std::size_t trie_id) {
- if (trie_id == config.num_tries()) {
- Vector<Entry> entries;
- entries.resize(keys.size());
- for (std::size_t i = 0; i < keys.size(); ++i) {
- entries[i].set_str(keys[i].ptr(), keys[i].length());
- }
- tail_.build(entries, terminals, config.tail_mode());
- return;
- }
- next_trie_.reset(new (std::nothrow) LoudsTrie);
- MARISA_THROW_IF(next_trie_.get() == NULL, MARISA_MEMORY_ERROR);
- next_trie_->build_trie(keys, terminals, config, trie_id + 1);
-}
-
-template <typename T>
-void LoudsTrie::build_terminals(const Vector<T> &keys,
- Vector<UInt32> *terminals) const {
- Vector<UInt32> temp;
- temp.resize(keys.size());
- for (std::size_t i = 0; i < keys.size(); ++i) {
- temp[keys[i].id()] = (UInt32)keys[i].terminal();
- }
- terminals->swap(temp);
-}
-
-template <>
-void LoudsTrie::cache<Key>(std::size_t parent, std::size_t child,
- float weight, char label) {
- MARISA_DEBUG_IF(parent >= child, MARISA_RANGE_ERROR);
-
- const std::size_t cache_id = get_cache_id(parent, label);
- if (weight > cache_[cache_id].weight()) {
- cache_[cache_id].set_parent(parent);
- cache_[cache_id].set_child(child);
- cache_[cache_id].set_weight(weight);
- }
-}
-
-void LoudsTrie::reserve_cache(const Config &config, std::size_t trie_id,
- std::size_t num_keys) {
- std::size_t cache_size = (trie_id == 1) ? 256 : 1;
- while (cache_size < (num_keys / config.cache_level())) {
- cache_size *= 2;
- }
- cache_.resize(cache_size);
- cache_mask_ = cache_size - 1;
-}
-
-template <>
-void LoudsTrie::cache<ReverseKey>(std::size_t parent, std::size_t child,
- float weight, char) {
- MARISA_DEBUG_IF(parent >= child, MARISA_RANGE_ERROR);
-
- const std::size_t cache_id = get_cache_id(child);
- if (weight > cache_[cache_id].weight()) {
- cache_[cache_id].set_parent(parent);
- cache_[cache_id].set_child(child);
- cache_[cache_id].set_weight(weight);
- }
-}
-
-void LoudsTrie::fill_cache() {
- for (std::size_t i = 0; i < cache_.size(); ++i) {
- const std::size_t node_id = cache_[i].child();
- if (node_id != 0) {
- cache_[i].set_base(bases_[node_id]);
- cache_[i].set_extra(!link_flags_[node_id] ?
- MARISA_INVALID_EXTRA : extras_[link_flags_.rank1(node_id)]);
- } else {
- cache_[i].set_parent(MARISA_UINT32_MAX);
- cache_[i].set_child(MARISA_UINT32_MAX);
- }
- }
-}
-
-void LoudsTrie::map_(Mapper &mapper) {
- louds_.map(mapper);
- terminal_flags_.map(mapper);
- link_flags_.map(mapper);
- bases_.map(mapper);
- extras_.map(mapper);
- tail_.map(mapper);
- if ((link_flags_.num_1s() != 0) && tail_.empty()) {
- next_trie_.reset(new (std::nothrow) LoudsTrie);
- MARISA_THROW_IF(next_trie_.get() == NULL, MARISA_MEMORY_ERROR);
- next_trie_->map_(mapper);
- }
- cache_.map(mapper);
- cache_mask_ = cache_.size() - 1;
- {
- UInt32 temp_num_l1_nodes;
- mapper.map(&temp_num_l1_nodes);
- num_l1_nodes_ = temp_num_l1_nodes;
- }
- {
- UInt32 temp_config_flags;
- mapper.map(&temp_config_flags);
- config_.parse((int)temp_config_flags);
- }
-}
-
-void LoudsTrie::read_(Reader &reader) {
- louds_.read(reader);
- terminal_flags_.read(reader);
- link_flags_.read(reader);
- bases_.read(reader);
- extras_.read(reader);
- tail_.read(reader);
- if ((link_flags_.num_1s() != 0) && tail_.empty()) {
- next_trie_.reset(new (std::nothrow) LoudsTrie);
- MARISA_THROW_IF(next_trie_.get() == NULL, MARISA_MEMORY_ERROR);
- next_trie_->read_(reader);
- }
- cache_.read(reader);
- cache_mask_ = cache_.size() - 1;
- {
- UInt32 temp_num_l1_nodes;
- reader.read(&temp_num_l1_nodes);
- num_l1_nodes_ = temp_num_l1_nodes;
- }
- {
- UInt32 temp_config_flags;
- reader.read(&temp_config_flags);
- config_.parse((int)temp_config_flags);
- }
-}
-
-void LoudsTrie::write_(Writer &writer) const {
- louds_.write(writer);
- terminal_flags_.write(writer);
- link_flags_.write(writer);
- bases_.write(writer);
- extras_.write(writer);
- tail_.write(writer);
- if (next_trie_.get() != NULL) {
- next_trie_->write_(writer);
- }
- cache_.write(writer);
- writer.write((UInt32)num_l1_nodes_);
- writer.write((UInt32)config_.flags());
-}
-
-bool LoudsTrie::find_child(Agent &agent) const {
- MARISA_DEBUG_IF(agent.state().query_pos() >= agent.query().length(),
- MARISA_BOUND_ERROR);
-
- State &state = agent.state();
- const std::size_t cache_id = get_cache_id(state.node_id(),
- agent.query()[state.query_pos()]);
- if (state.node_id() == cache_[cache_id].parent()) {
- if (cache_[cache_id].extra() != MARISA_INVALID_EXTRA) {
- if (!match(agent, cache_[cache_id].link())) {
- return false;
- }
- } else {
- state.set_query_pos(state.query_pos() + 1);
- }
- state.set_node_id(cache_[cache_id].child());
- return true;
- }
-
- std::size_t louds_pos = louds_.select0(state.node_id()) + 1;
- if (!louds_[louds_pos]) {
- return false;
- }
- state.set_node_id(louds_pos - state.node_id() - 1);
- std::size_t link_id = MARISA_INVALID_LINK_ID;
- do {
- if (link_flags_[state.node_id()]) {
- link_id = update_link_id(link_id, state.node_id());
- const std::size_t prev_query_pos = state.query_pos();
- if (match(agent, get_link(state.node_id(), link_id))) {
- return true;
- } else if (state.query_pos() != prev_query_pos) {
- return false;
- }
- } else if (bases_[state.node_id()] ==
- (UInt8)agent.query()[state.query_pos()]) {
- state.set_query_pos(state.query_pos() + 1);
- return true;
- }
- state.set_node_id(state.node_id() + 1);
- ++louds_pos;
- } while (louds_[louds_pos]);
- return false;
-}
-
-bool LoudsTrie::predictive_find_child(Agent &agent) const {
- MARISA_DEBUG_IF(agent.state().query_pos() >= agent.query().length(),
- MARISA_BOUND_ERROR);
-
- State &state = agent.state();
- const std::size_t cache_id = get_cache_id(state.node_id(),
- agent.query()[state.query_pos()]);
- if (state.node_id() == cache_[cache_id].parent()) {
- if (cache_[cache_id].extra() != MARISA_INVALID_EXTRA) {
- if (!prefix_match(agent, cache_[cache_id].link())) {
- return false;
- }
- } else {
- state.key_buf().push_back(cache_[cache_id].label());
- state.set_query_pos(state.query_pos() + 1);
- }
- state.set_node_id(cache_[cache_id].child());
- return true;
- }
-
- std::size_t louds_pos = louds_.select0(state.node_id()) + 1;
- if (!louds_[louds_pos]) {
- return false;
- }
- state.set_node_id(louds_pos - state.node_id() - 1);
- std::size_t link_id = MARISA_INVALID_LINK_ID;
- do {
- if (link_flags_[state.node_id()]) {
- link_id = update_link_id(link_id, state.node_id());
- const std::size_t prev_query_pos = state.query_pos();
- if (prefix_match(agent, get_link(state.node_id(), link_id))) {
- return true;
- } else if (state.query_pos() != prev_query_pos) {
- return false;
- }
- } else if (bases_[state.node_id()] ==
- (UInt8)agent.query()[state.query_pos()]) {
- state.key_buf().push_back((char)bases_[state.node_id()]);
- state.set_query_pos(state.query_pos() + 1);
- return true;
- }
- state.set_node_id(state.node_id() + 1);
- ++louds_pos;
- } while (louds_[louds_pos]);
- return false;
-}
-
-void LoudsTrie::restore(Agent &agent, std::size_t link) const {
- if (next_trie_.get() != NULL) {
- next_trie_->restore_(agent, link);
- } else {
- tail_.restore(agent, link);
- }
-}
-
-bool LoudsTrie::match(Agent &agent, std::size_t link) const {
- if (next_trie_.get() != NULL) {
- return next_trie_->match_(agent, link);
- } else {
- return tail_.match(agent, link);
- }
-}
-
-bool LoudsTrie::prefix_match(Agent &agent, std::size_t link) const {
- if (next_trie_.get() != NULL) {
- return next_trie_->prefix_match_(agent, link);
- } else {
- return tail_.prefix_match(agent, link);
- }
-}
-
-void LoudsTrie::restore_(Agent &agent, std::size_t node_id) const {
- MARISA_DEBUG_IF(node_id == 0, MARISA_RANGE_ERROR);
-
- State &state = agent.state();
- for ( ; ; ) {
- const std::size_t cache_id = get_cache_id(node_id);
- if (node_id == cache_[cache_id].child()) {
- if (cache_[cache_id].extra() != MARISA_INVALID_EXTRA) {
- restore(agent, cache_[cache_id].link());
- } else {
- state.key_buf().push_back(cache_[cache_id].label());
- }
-
- node_id = cache_[cache_id].parent();
- if (node_id == 0) {
- return;
- }
- continue;
- }
-
- if (link_flags_[node_id]) {
- restore(agent, get_link(node_id));
- } else {
- state.key_buf().push_back((char)bases_[node_id]);
- }
-
- if (node_id <= num_l1_nodes_) {
- return;
- }
- node_id = louds_.select1(node_id) - node_id - 1;
- }
-}
-
-bool LoudsTrie::match_(Agent &agent, std::size_t node_id) const {
- MARISA_DEBUG_IF(agent.state().query_pos() >= agent.query().length(),
- MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(node_id == 0, MARISA_RANGE_ERROR);
-
- State &state = agent.state();
- for ( ; ; ) {
- const std::size_t cache_id = get_cache_id(node_id);
- if (node_id == cache_[cache_id].child()) {
- if (cache_[cache_id].extra() != MARISA_INVALID_EXTRA) {
- if (!match(agent, cache_[cache_id].link())) {
- return false;
- }
- } else if (cache_[cache_id].label() ==
- agent.query()[state.query_pos()]) {
- state.set_query_pos(state.query_pos() + 1);
- } else {
- return false;
- }
-
- node_id = cache_[cache_id].parent();
- if (node_id == 0) {
- return true;
- } else if (state.query_pos() >= agent.query().length()) {
- return false;
- }
- continue;
- }
-
- if (link_flags_[node_id]) {
- if (next_trie_.get() != NULL) {
- if (!match(agent, get_link(node_id))) {
- return false;
- }
- } else if (!tail_.match(agent, get_link(node_id))) {
- return false;
- }
- } else if (bases_[node_id] == (UInt8)agent.query()[state.query_pos()]) {
- state.set_query_pos(state.query_pos() + 1);
- } else {
- return false;
- }
-
- if (node_id <= num_l1_nodes_) {
- return true;
- } else if (state.query_pos() >= agent.query().length()) {
- return false;
- }
- node_id = louds_.select1(node_id) - node_id - 1;
- }
-}
-
-bool LoudsTrie::prefix_match_(Agent &agent, std::size_t node_id) const {
- MARISA_DEBUG_IF(agent.state().query_pos() >= agent.query().length(),
- MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(node_id == 0, MARISA_RANGE_ERROR);
-
- State &state = agent.state();
- for ( ; ; ) {
- const std::size_t cache_id = get_cache_id(node_id);
- if (node_id == cache_[cache_id].child()) {
- if (cache_[cache_id].extra() != MARISA_INVALID_EXTRA) {
- if (!prefix_match(agent, cache_[cache_id].link())) {
- return false;
- }
- } else if (cache_[cache_id].label() ==
- agent.query()[state.query_pos()]) {
- state.key_buf().push_back(cache_[cache_id].label());
- state.set_query_pos(state.query_pos() + 1);
- } else {
- return false;
- }
-
- node_id = cache_[cache_id].parent();
- if (node_id == 0) {
- return true;
- }
- } else {
- if (link_flags_[node_id]) {
- if (!prefix_match(agent, get_link(node_id))) {
- return false;
- }
- } else if (bases_[node_id] == (UInt8)agent.query()[state.query_pos()]) {
- state.key_buf().push_back((char)bases_[node_id]);
- state.set_query_pos(state.query_pos() + 1);
- } else {
- return false;
- }
-
- if (node_id <= num_l1_nodes_) {
- return true;
- }
- node_id = louds_.select1(node_id) - node_id - 1;
- }
-
- if (state.query_pos() >= agent.query().length()) {
- restore_(agent, node_id);
- return true;
- }
- }
-}
-
-std::size_t LoudsTrie::get_cache_id(std::size_t node_id, char label) const {
- return (node_id ^ (node_id << 5) ^ (UInt8)label) & cache_mask_;
-}
-
-std::size_t LoudsTrie::get_cache_id(std::size_t node_id) const {
- return node_id & cache_mask_;
-}
-
-std::size_t LoudsTrie::get_link(std::size_t node_id) const {
- return bases_[node_id] | (extras_[link_flags_.rank1(node_id)] * 256);
-}
-
-std::size_t LoudsTrie::get_link(std::size_t node_id,
- std::size_t link_id) const {
- return bases_[node_id] | (extras_[link_id] * 256);
-}
-
-std::size_t LoudsTrie::update_link_id(std::size_t link_id,
- std::size_t node_id) const {
- return (link_id == MARISA_INVALID_LINK_ID) ?
- link_flags_.rank1(node_id) : (link_id + 1);
-}
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_LOUDS_TRIE_H_
-#define MARISA_GRIMOIRE_TRIE_LOUDS_TRIE_H_
-
-#include "marisa/keyset.h"
-#include "marisa/agent.h"
-#include "marisa/grimoire/vector.h"
-#include "marisa/grimoire/trie/config.h"
-#include "marisa/grimoire/trie/key.h"
-#include "marisa/grimoire/trie/tail.h"
-#include "marisa/grimoire/trie/cache.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class LoudsTrie {
- public:
- LoudsTrie();
- ~LoudsTrie();
-
- void build(Keyset &keyset, int flags);
-
- void map(Mapper &mapper);
- void read(Reader &reader);
- void write(Writer &writer) const;
-
- bool lookup(Agent &agent) const;
- void reverse_lookup(Agent &agent) const;
- bool common_prefix_search(Agent &agent) const;
- bool predictive_search(Agent &agent) const;
-
- std::size_t num_tries() const {
- return config_.num_tries();
- }
- std::size_t num_keys() const {
- return size();
- }
- std::size_t num_nodes() const {
- return (louds_.size() / 2) - 1;
- }
-
- CacheLevel cache_level() const {
- return config_.cache_level();
- }
- TailMode tail_mode() const {
- return config_.tail_mode();
- }
- NodeOrder node_order() const {
- return config_.node_order();
- }
-
- bool empty() const {
- return size() == 0;
- }
- std::size_t size() const {
- return terminal_flags_.num_1s();
- }
- std::size_t total_size() const;
- std::size_t io_size() const;
-
- void clear();
- void swap(LoudsTrie &rhs);
-
- private:
- BitVector louds_;
- BitVector terminal_flags_;
- BitVector link_flags_;
- Vector<UInt8> bases_;
- FlatVector extras_;
- Tail tail_;
- scoped_ptr<LoudsTrie> next_trie_;
- Vector<Cache> cache_;
- std::size_t cache_mask_;
- std::size_t num_l1_nodes_;
- Config config_;
- Mapper mapper_;
-
- void build_(Keyset &keyset, const Config &config);
-
- template <typename T>
- void build_trie(Vector<T> &keys,
- Vector<UInt32> *terminals, const Config &config, std::size_t trie_id);
- template <typename T>
- void build_current_trie(Vector<T> &keys,
- Vector<UInt32> *terminals, const Config &config, std::size_t trie_id);
- template <typename T>
- void build_next_trie(Vector<T> &keys,
- Vector<UInt32> *terminals, const Config &config, std::size_t trie_id);
- template <typename T>
- void build_terminals(const Vector<T> &keys,
- Vector<UInt32> *terminals) const;
-
- void reserve_cache(const Config &config, std::size_t trie_id,
- std::size_t num_keys);
- template <typename T>
- void cache(std::size_t parent, std::size_t child,
- float weight, char label);
- void fill_cache();
-
- void map_(Mapper &mapper);
- void read_(Reader &reader);
- void write_(Writer &writer) const;
-
- inline bool find_child(Agent &agent) const;
- inline bool predictive_find_child(Agent &agent) const;
-
- inline void restore(Agent &agent, std::size_t node_id) const;
- inline bool match(Agent &agent, std::size_t node_id) const;
- inline bool prefix_match(Agent &agent, std::size_t node_id) const;
-
- void restore_(Agent &agent, std::size_t node_id) const;
- bool match_(Agent &agent, std::size_t node_id) const;
- bool prefix_match_(Agent &agent, std::size_t node_id) const;
-
- inline std::size_t get_cache_id(std::size_t node_id, char label) const;
- inline std::size_t get_cache_id(std::size_t node_id) const;
-
- inline std::size_t get_link(std::size_t node_id) const;
- inline std::size_t get_link(std::size_t node_id,
- std::size_t link_id) const;
-
- inline std::size_t update_link_id(std::size_t link_id,
- std::size_t node_id) const;
-
- // Disallows copy and assignment.
- LoudsTrie(const LoudsTrie &);
- LoudsTrie &operator=(const LoudsTrie &);
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_LOUDS_TRIE_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_RANGE_H_
-#define MARISA_GRIMOIRE_TRIE_RANGE_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Range {
- public:
- Range() : begin_(0), end_(0), key_pos_(0) {}
-
- void set_begin(std::size_t begin) {
- MARISA_DEBUG_IF(begin > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- begin_ = static_cast<UInt32>(begin);
- }
- void set_end(std::size_t end) {
- MARISA_DEBUG_IF(end > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- end_ = static_cast<UInt32>(end);
- }
- void set_key_pos(std::size_t key_pos) {
- MARISA_DEBUG_IF(key_pos > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- key_pos_ = static_cast<UInt32>(key_pos);
- }
-
- std::size_t begin() const {
- return begin_;
- }
- std::size_t end() const {
- return end_;
- }
- std::size_t key_pos() const {
- return key_pos_;
- }
-
- private:
- UInt32 begin_;
- UInt32 end_;
- UInt32 key_pos_;
-};
-
-inline Range make_range(std::size_t begin, std::size_t end,
- std::size_t key_pos) {
- Range range;
- range.set_begin(begin);
- range.set_end(end);
- range.set_key_pos(key_pos);
- return range;
-}
-
-class WeightedRange {
- public:
- WeightedRange() : range_(), weight_(0.0F) {}
-
- void set_range(const Range &range) {
- range_ = range;
- }
- void set_begin(std::size_t begin) {
- range_.set_begin(begin);
- }
- void set_end(std::size_t end) {
- range_.set_end(end);
- }
- void set_key_pos(std::size_t key_pos) {
- range_.set_key_pos(key_pos);
- }
- void set_weight(float weight) {
- weight_ = weight;
- }
-
- const Range &range() const {
- return range_;
- }
- std::size_t begin() const {
- return range_.begin();
- }
- std::size_t end() const {
- return range_.end();
- }
- std::size_t key_pos() const {
- return range_.key_pos();
- }
- float weight() const {
- return weight_;
- }
-
- private:
- Range range_;
- float weight_;
-};
-
-inline bool operator<(const WeightedRange &lhs, const WeightedRange &rhs) {
- return lhs.weight() < rhs.weight();
-}
-
-inline bool operator>(const WeightedRange &lhs, const WeightedRange &rhs) {
- return lhs.weight() > rhs.weight();
-}
-
-inline WeightedRange make_weighted_range(std::size_t begin, std::size_t end,
- std::size_t key_pos, float weight) {
- WeightedRange range;
- range.set_begin(begin);
- range.set_end(end);
- range.set_key_pos(key_pos);
- range.set_weight(weight);
- return range;
-}
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_RANGE_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_STATE_H_
-#define MARISA_GRIMOIRE_TRIE_STATE_H_
-
-#include "marisa/grimoire/vector.h"
-#include "marisa/grimoire/trie/history.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-// A search agent has its internal state and the status codes are defined
-// below.
-typedef enum StatusCode {
- MARISA_READY_TO_ALL,
- MARISA_READY_TO_COMMON_PREFIX_SEARCH,
- MARISA_READY_TO_PREDICTIVE_SEARCH,
- MARISA_END_OF_COMMON_PREFIX_SEARCH,
- MARISA_END_OF_PREDICTIVE_SEARCH,
-} StatusCode;
-
-class State {
- public:
- State()
- : key_buf_(), history_(), node_id_(0), query_pos_(0),
- history_pos_(0), status_code_(MARISA_READY_TO_ALL) {}
-
- void set_node_id(std::size_t node_id) {
- MARISA_DEBUG_IF(node_id > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- node_id_ = (UInt32)node_id;
- }
- void set_query_pos(std::size_t query_pos) {
- MARISA_DEBUG_IF(query_pos > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- query_pos_ = (UInt32)query_pos;
- }
- void set_history_pos(std::size_t history_pos) {
- MARISA_DEBUG_IF(history_pos > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- history_pos_ = (UInt32)history_pos;
- }
- void set_status_code(StatusCode status_code) {
- status_code_ = status_code;
- }
-
- std::size_t node_id() const {
- return node_id_;
- }
- std::size_t query_pos() const {
- return query_pos_;
- }
- std::size_t history_pos() const {
- return history_pos_;
- }
- StatusCode status_code() const {
- return status_code_;
- }
-
- const Vector<char> &key_buf() const {
- return key_buf_;
- }
- const Vector<History> &history() const {
- return history_;
- }
-
- Vector<char> &key_buf() {
- return key_buf_;
- }
- Vector<History> &history() {
- return history_;
- }
-
- void reset() {
- status_code_ = MARISA_READY_TO_ALL;
- }
-
- void lookup_init() {
- node_id_ = 0;
- query_pos_ = 0;
- status_code_ = MARISA_READY_TO_ALL;
- }
- void reverse_lookup_init() {
- key_buf_.resize(0);
- key_buf_.reserve(32);
- status_code_ = MARISA_READY_TO_ALL;
- }
- void common_prefix_search_init() {
- node_id_ = 0;
- query_pos_ = 0;
- status_code_ = MARISA_READY_TO_COMMON_PREFIX_SEARCH;
- }
- void predictive_search_init() {
- key_buf_.resize(0);
- key_buf_.reserve(64);
- history_.resize(0);
- history_.reserve(4);
- node_id_ = 0;
- query_pos_ = 0;
- history_pos_ = 0;
- status_code_ = MARISA_READY_TO_PREDICTIVE_SEARCH;
- }
-
- private:
- Vector<char> key_buf_;
- Vector<History> history_;
- UInt32 node_id_;
- UInt32 query_pos_;
- UInt32 history_pos_;
- StatusCode status_code_;
-
- // Disallows copy and assignment.
- State(const State &);
- State &operator=(const State &);
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_STATE_H_
+++ /dev/null
-#include "marisa/grimoire/algorithm.h"
-#include "marisa/grimoire/trie/state.h"
-#include "marisa/grimoire/trie/tail.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-Tail::Tail() : buf_(), end_flags_() {}
-
-void Tail::build(Vector<Entry> &entries, Vector<UInt32> *offsets,
- TailMode mode) {
- MARISA_THROW_IF(offsets == NULL, MARISA_NULL_ERROR);
-
- switch (mode) {
- case MARISA_TEXT_TAIL: {
- for (std::size_t i = 0; i < entries.size(); ++i) {
- const char * const ptr = entries[i].ptr();
- const std::size_t length = entries[i].length();
- for (std::size_t j = 0; j < length; ++j) {
- if (ptr[j] == '\0') {
- mode = MARISA_BINARY_TAIL;
- break;
- }
- }
- if (mode == MARISA_BINARY_TAIL) {
- break;
- }
- }
- break;
- }
- case MARISA_BINARY_TAIL: {
- break;
- }
- default: {
- MARISA_THROW(MARISA_CODE_ERROR, "undefined tail mode");
- }
- }
-
- Tail temp;
- temp.build_(entries, offsets, mode);
- swap(temp);
-}
-
-void Tail::map(Mapper &mapper) {
- Tail temp;
- temp.map_(mapper);
- swap(temp);
-}
-
-void Tail::read(Reader &reader) {
- Tail temp;
- temp.read_(reader);
- swap(temp);
-}
-
-void Tail::write(Writer &writer) const {
- write_(writer);
-}
-
-void Tail::restore(Agent &agent, std::size_t offset) const {
- MARISA_DEBUG_IF(buf_.empty(), MARISA_STATE_ERROR);
-
- State &state = agent.state();
- if (end_flags_.empty()) {
- for (const char *ptr = &buf_[offset]; *ptr != '\0'; ++ptr) {
- state.key_buf().push_back(*ptr);
- }
- } else {
- do {
- state.key_buf().push_back(buf_[offset]);
- } while (!end_flags_[offset++]);
- }
-}
-
-bool Tail::match(Agent &agent, std::size_t offset) const {
- MARISA_DEBUG_IF(buf_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(agent.state().query_pos() >= agent.query().length(),
- MARISA_BOUND_ERROR);
-
- State &state = agent.state();
- if (end_flags_.empty()) {
- const char * const ptr = &buf_[offset] - state.query_pos();
- do {
- if (ptr[state.query_pos()] != agent.query()[state.query_pos()]) {
- return false;
- }
- state.set_query_pos(state.query_pos() + 1);
- if (ptr[state.query_pos()] == '\0') {
- return true;
- }
- } while (state.query_pos() < agent.query().length());
- return false;
- } else {
- do {
- if (buf_[offset] != agent.query()[state.query_pos()]) {
- return false;
- }
- state.set_query_pos(state.query_pos() + 1);
- if (end_flags_[offset++]) {
- return true;
- }
- } while (state.query_pos() < agent.query().length());
- return false;
- }
-}
-
-bool Tail::prefix_match(Agent &agent, std::size_t offset) const {
- MARISA_DEBUG_IF(buf_.empty(), MARISA_STATE_ERROR);
-
- State &state = agent.state();
- if (end_flags_.empty()) {
- const char *ptr = &buf_[offset] - state.query_pos();
- do {
- if (ptr[state.query_pos()] != agent.query()[state.query_pos()]) {
- return false;
- }
- state.key_buf().push_back(ptr[state.query_pos()]);
- state.set_query_pos(state.query_pos() + 1);
- if (ptr[state.query_pos()] == '\0') {
- return true;
- }
- } while (state.query_pos() < agent.query().length());
- ptr += state.query_pos();
- do {
- state.key_buf().push_back(*ptr);
- } while (*++ptr != '\0');
- return true;
- } else {
- do {
- if (buf_[offset] != agent.query()[state.query_pos()]) {
- return false;
- }
- state.key_buf().push_back(buf_[offset]);
- state.set_query_pos(state.query_pos() + 1);
- if (end_flags_[offset++]) {
- return true;
- }
- } while (state.query_pos() < agent.query().length());
- do {
- state.key_buf().push_back(buf_[offset]);
- } while (!end_flags_[offset++]);
- return true;
- }
-}
-
-void Tail::clear() {
- Tail().swap(*this);
-}
-
-void Tail::swap(Tail &rhs) {
- buf_.swap(rhs.buf_);
- end_flags_.swap(rhs.end_flags_);
-}
-
-void Tail::build_(Vector<Entry> &entries, Vector<UInt32> *offsets,
- TailMode mode) {
- for (std::size_t i = 0; i < entries.size(); ++i) {
- entries[i].set_id(i);
- }
- Algorithm().sort(entries.begin(), entries.end());
-
- Vector<UInt32> temp_offsets;
- temp_offsets.resize(entries.size(), 0);
-
- const Entry dummy;
- const Entry *last = &dummy;
- for (std::size_t i = entries.size(); i > 0; --i) {
- const Entry ¤t = entries[i - 1];
- MARISA_THROW_IF(current.length() == 0, MARISA_RANGE_ERROR);
- std::size_t match = 0;
- while ((match < current.length()) && (match < last->length()) &&
- ((*last)[match] == current[match])) {
- ++match;
- }
- if ((match == current.length()) && (last->length() != 0)) {
- temp_offsets[current.id()] = (UInt32)(
- temp_offsets[last->id()] + (last->length() - match));
- } else {
- temp_offsets[current.id()] = (UInt32)buf_.size();
- for (std::size_t j = 1; j <= current.length(); ++j) {
- buf_.push_back(current[current.length() - j]);
- }
- if (mode == MARISA_TEXT_TAIL) {
- buf_.push_back('\0');
- } else {
- for (std::size_t j = 1; j < current.length(); ++j) {
- end_flags_.push_back(false);
- }
- end_flags_.push_back(true);
- }
- MARISA_THROW_IF(buf_.size() > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- }
- last = ¤t;
- }
- buf_.shrink();
-
- offsets->swap(temp_offsets);
-}
-
-void Tail::map_(Mapper &mapper) {
- buf_.map(mapper);
- end_flags_.map(mapper);
-}
-
-void Tail::read_(Reader &reader) {
- buf_.read(reader);
- end_flags_.read(reader);
-}
-
-void Tail::write_(Writer &writer) const {
- buf_.write(writer);
- end_flags_.write(writer);
-}
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_TRIE_TAIL_H_
-#define MARISA_GRIMOIRE_TRIE_TAIL_H_
-
-#include "marisa/agent.h"
-#include "marisa/grimoire/vector.h"
-#include "marisa/grimoire/trie/entry.h"
-
-namespace marisa {
-namespace grimoire {
-namespace trie {
-
-class Tail {
- public:
- Tail();
-
- void build(Vector<Entry> &entries, Vector<UInt32> *offsets,
- TailMode mode);
-
- void map(Mapper &mapper);
- void read(Reader &reader);
- void write(Writer &writer) const;
-
- void restore(Agent &agent, std::size_t offset) const;
- bool match(Agent &agent, std::size_t offset) const;
- bool prefix_match(Agent &agent, std::size_t offset) const;
-
- const char &operator[](std::size_t offset) const {
- MARISA_DEBUG_IF(offset >= buf_.size(), MARISA_BOUND_ERROR);
- return buf_[offset];
- }
-
- TailMode mode() const {
- return end_flags_.empty() ? MARISA_TEXT_TAIL : MARISA_BINARY_TAIL;
- }
-
- bool empty() const {
- return buf_.empty();
- }
- std::size_t size() const {
- return buf_.size();
- }
- std::size_t total_size() const {
- return buf_.total_size() + end_flags_.total_size();
- }
- std::size_t io_size() const {
- return buf_.io_size() + end_flags_.io_size();
- }
-
- void clear();
- void swap(Tail &rhs);
-
- private:
- Vector<char> buf_;
- BitVector end_flags_;
-
- void build_(Vector<Entry> &entries, Vector<UInt32> *offsets,
- TailMode mode);
-
- void map_(Mapper &mapper);
- void read_(Reader &reader);
- void write_(Writer &writer) const;
-
- // Disallows copy and assignment.
- Tail(const Tail &);
- Tail &operator=(const Tail &);
-};
-
-} // namespace trie
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_TRIE_TAIL_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_VECTOR_H_
-#define MARISA_GRIMOIRE_VECTOR_H_
-
-#include "marisa/grimoire/vector/vector.h"
-#include "marisa/grimoire/vector/flat-vector.h"
-#include "marisa/grimoire/vector/bit-vector.h"
-
-namespace marisa {
-namespace grimoire {
-
-using vector::Vector;
-typedef vector::FlatVector FlatVector;
-typedef vector::BitVector BitVector;
-
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_VECTOR_H_
+++ /dev/null
-#include "marisa/grimoire/vector/pop-count.h"
-#include "marisa/grimoire/vector/bit-vector.h"
-
-namespace marisa {
-namespace grimoire {
-namespace vector {
-namespace {
-
-const UInt8 SELECT_TABLE[8][256] = {
- {
- 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
- 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
- },
- {
- 7, 7, 7, 1, 7, 2, 2, 1, 7, 3, 3, 1, 3, 2, 2, 1,
- 7, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 7, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
- 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 7, 6, 6, 1, 6, 2, 2, 1, 6, 3, 3, 1, 3, 2, 2, 1,
- 6, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 6, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
- 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 7, 7, 7, 1, 7, 2, 2, 1, 7, 3, 3, 1, 3, 2, 2, 1,
- 7, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 7, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
- 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 7, 6, 6, 1, 6, 2, 2, 1, 6, 3, 3, 1, 3, 2, 2, 1,
- 6, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1,
- 6, 5, 5, 1, 5, 2, 2, 1, 5, 3, 3, 1, 3, 2, 2, 1,
- 5, 4, 4, 1, 4, 2, 2, 1, 4, 3, 3, 1, 3, 2, 2, 1
- },
- {
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 3, 7, 3, 3, 2,
- 7, 7, 7, 4, 7, 4, 4, 2, 7, 4, 4, 3, 4, 3, 3, 2,
- 7, 7, 7, 5, 7, 5, 5, 2, 7, 5, 5, 3, 5, 3, 3, 2,
- 7, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
- 7, 7, 7, 6, 7, 6, 6, 2, 7, 6, 6, 3, 6, 3, 3, 2,
- 7, 6, 6, 4, 6, 4, 4, 2, 6, 4, 4, 3, 4, 3, 3, 2,
- 7, 6, 6, 5, 6, 5, 5, 2, 6, 5, 5, 3, 5, 3, 3, 2,
- 6, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 3, 7, 3, 3, 2,
- 7, 7, 7, 4, 7, 4, 4, 2, 7, 4, 4, 3, 4, 3, 3, 2,
- 7, 7, 7, 5, 7, 5, 5, 2, 7, 5, 5, 3, 5, 3, 3, 2,
- 7, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2,
- 7, 7, 7, 6, 7, 6, 6, 2, 7, 6, 6, 3, 6, 3, 3, 2,
- 7, 6, 6, 4, 6, 4, 4, 2, 6, 4, 4, 3, 4, 3, 3, 2,
- 7, 6, 6, 5, 6, 5, 5, 2, 6, 5, 5, 3, 5, 3, 3, 2,
- 6, 5, 5, 4, 5, 4, 4, 2, 5, 4, 4, 3, 4, 3, 3, 2
- },
- {
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3,
- 7, 7, 7, 7, 7, 7, 7, 4, 7, 7, 7, 4, 7, 4, 4, 3,
- 7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 3,
- 7, 7, 7, 5, 7, 5, 5, 4, 7, 5, 5, 4, 5, 4, 4, 3,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 3,
- 7, 7, 7, 6, 7, 6, 6, 4, 7, 6, 6, 4, 6, 4, 4, 3,
- 7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 3,
- 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 3,
- 7, 7, 7, 7, 7, 7, 7, 4, 7, 7, 7, 4, 7, 4, 4, 3,
- 7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 3,
- 7, 7, 7, 5, 7, 5, 5, 4, 7, 5, 5, 4, 5, 4, 4, 3,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 3,
- 7, 7, 7, 6, 7, 6, 6, 4, 7, 6, 6, 4, 6, 4, 4, 3,
- 7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 3,
- 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3
- },
- {
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
- 7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 4,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 4,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5,
- 7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
- 7, 7, 7, 7, 7, 7, 7, 5, 7, 7, 7, 5, 7, 5, 5, 4,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 4,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5,
- 7, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4
- },
- {
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 6, 7, 7, 7, 6, 7, 6, 6, 5
- },
- {
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6
- },
- {
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
- }
-};
-
-#if MARISA_WORD_SIZE == 64
-const UInt64 MASK_55 = 0x5555555555555555ULL;
-const UInt64 MASK_33 = 0x3333333333333333ULL;
-const UInt64 MASK_0F = 0x0F0F0F0F0F0F0F0FULL;
-const UInt64 MASK_01 = 0x0101010101010101ULL;
-const UInt64 MASK_80 = 0x8080808080808080ULL;
-
-std::size_t select_bit(std::size_t i, std::size_t bit_id, UInt64 unit) {
- UInt64 counts;
- {
- #if defined(MARISA_X64) && defined(MARISA_USE_SSSE3)
- __m128i lower_nibbles = _mm_cvtsi64_si128(unit & 0x0F0F0F0F0F0F0F0FULL);
- __m128i upper_nibbles = _mm_cvtsi64_si128(unit & 0xF0F0F0F0F0F0F0F0ULL);
- upper_nibbles = _mm_srli_epi32(upper_nibbles, 4);
-
- __m128i lower_counts =
- _mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0);
- lower_counts = _mm_shuffle_epi8(lower_counts, lower_nibbles);
- __m128i upper_counts =
- _mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0);
- upper_counts = _mm_shuffle_epi8(upper_counts, upper_nibbles);
-
- counts = _mm_cvtsi128_si64(_mm_add_epi8(lower_counts, upper_counts));
- #else // defined(MARISA_X64) && defined(MARISA_USE_SSSE3)
- counts = unit - ((unit >> 1) & MASK_55);
- counts = (counts & MASK_33) + ((counts >> 2) & MASK_33);
- counts = (counts + (counts >> 4)) & MASK_0F;
- #endif // defined(MARISA_X64) && defined(MARISA_USE_SSSE3)
- counts *= MASK_01;
- }
-
- #if defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
- UInt8 skip;
- {
- __m128i x = _mm_cvtsi64_si128((i + 1) * MASK_01);
- __m128i y = _mm_cvtsi64_si128(counts);
- x = _mm_cmpgt_epi8(x, y);
- skip = (UInt8)PopCount::count(_mm_cvtsi128_si64(x));
- }
- #else // defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
- const UInt64 x = (counts | MASK_80) - ((i + 1) * MASK_01);
- #ifdef _MSC_VER
- unsigned long skip;
- ::_BitScanForward64(&skip, (x & MASK_80) >> 7);
- #else // _MSC_VER
- const int skip = ::__builtin_ctzll((x & MASK_80) >> 7);
- #endif // _MSC_VER
- #endif // defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
-
- bit_id += skip;
- unit >>= skip;
- i -= ((counts << 8) >> skip) & 0xFF;
-
- return bit_id + SELECT_TABLE[i][unit & 0xFF];
-}
-#else // MARISA_WORD_SIZE == 64
- #ifdef MARISA_USE_SSE2
-const UInt8 POPCNT_TABLE[256] = {
- 0, 8, 8, 16, 8, 16, 16, 24, 8, 16, 16, 24, 16, 24, 24, 32,
- 8, 16, 16, 24, 16, 24, 24, 32, 16, 24, 24, 32, 24, 32, 32, 40,
- 8, 16, 16, 24, 16, 24, 24, 32, 16, 24, 24, 32, 24, 32, 32, 40,
- 16, 24, 24, 32, 24, 32, 32, 40, 24, 32, 32, 40, 32, 40, 40, 48,
- 8, 16, 16, 24, 16, 24, 24, 32, 16, 24, 24, 32, 24, 32, 32, 40,
- 16, 24, 24, 32, 24, 32, 32, 40, 24, 32, 32, 40, 32, 40, 40, 48,
- 16, 24, 24, 32, 24, 32, 32, 40, 24, 32, 32, 40, 32, 40, 40, 48,
- 24, 32, 32, 40, 32, 40, 40, 48, 32, 40, 40, 48, 40, 48, 48, 56,
- 8, 16, 16, 24, 16, 24, 24, 32, 16, 24, 24, 32, 24, 32, 32, 40,
- 16, 24, 24, 32, 24, 32, 32, 40, 24, 32, 32, 40, 32, 40, 40, 48,
- 16, 24, 24, 32, 24, 32, 32, 40, 24, 32, 32, 40, 32, 40, 40, 48,
- 24, 32, 32, 40, 32, 40, 40, 48, 32, 40, 40, 48, 40, 48, 48, 56,
- 16, 24, 24, 32, 24, 32, 32, 40, 24, 32, 32, 40, 32, 40, 40, 48,
- 24, 32, 32, 40, 32, 40, 40, 48, 32, 40, 40, 48, 40, 48, 48, 56,
- 24, 32, 32, 40, 32, 40, 40, 48, 32, 40, 40, 48, 40, 48, 48, 56,
- 32, 40, 40, 48, 40, 48, 48, 56, 40, 48, 48, 56, 48, 56, 56, 64
-};
-
-std::size_t select_bit(std::size_t i, std::size_t bit_id,
- UInt32 unit_lo, UInt32 unit_hi) {
- __m128i unit;
- {
- __m128i lower_dword = _mm_cvtsi32_si128(unit_lo);
- __m128i upper_dword = _mm_cvtsi32_si128(unit_hi);
- upper_dword = _mm_slli_si128(upper_dword, 4);
- unit = _mm_or_si128(lower_dword, upper_dword);
- }
-
- __m128i counts;
- {
- #ifdef MARISA_USE_SSSE3
- __m128i lower_nibbles = _mm_set1_epi8(0x0F);
- lower_nibbles = _mm_and_si128(lower_nibbles, unit);
- __m128i upper_nibbles = _mm_set1_epi8((UInt8)0xF0);
- upper_nibbles = _mm_and_si128(upper_nibbles, unit);
- upper_nibbles = _mm_srli_epi32(upper_nibbles, 4);
-
- __m128i lower_counts =
- _mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0);
- lower_counts = _mm_shuffle_epi8(lower_counts, lower_nibbles);
- __m128i upper_counts =
- _mm_set_epi8(4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0);
- upper_counts = _mm_shuffle_epi8(upper_counts, upper_nibbles);
-
- counts = _mm_add_epi8(lower_counts, upper_counts);
- #else // MARISA_USE_SSSE3
- __m128i x = _mm_srli_epi32(unit, 1);
- x = _mm_and_si128(x, _mm_set1_epi8(0x55));
- x = _mm_sub_epi8(unit, x);
-
- __m128i y = _mm_srli_epi32(x, 2);
- y = _mm_and_si128(y, _mm_set1_epi8(0x33));
- x = _mm_and_si128(x, _mm_set1_epi8(0x33));
- x = _mm_add_epi8(x, y);
-
- y = _mm_srli_epi32(x, 4);
- x = _mm_add_epi8(x, y);
- counts = _mm_and_si128(x, _mm_set1_epi8(0x0F));
- #endif // MARISA_USE_SSSE3
- }
-
- __m128i accumulated_counts;
- {
- __m128i x = counts;
- x = _mm_slli_si128(x, 1);
- __m128i y = counts;
- y = _mm_add_epi32(y, x);
-
- x = y;
- y = _mm_slli_si128(y, 2);
- x = _mm_add_epi32(x, y);
-
- y = x;
- x = _mm_slli_si128(x, 4);
- y = _mm_add_epi32(y, x);
-
- accumulated_counts = _mm_set_epi32(0x7F7F7F7FU, 0x7F7F7F7FU, 0, 0);
- accumulated_counts = _mm_or_si128(accumulated_counts, y);
- }
-
- UInt8 skip;
- {
- __m128i x = _mm_set1_epi8((UInt8)(i + 1));
- x = _mm_cmpgt_epi8(x, accumulated_counts);
- skip = POPCNT_TABLE[_mm_movemask_epi8(x)];
- }
-
- UInt8 byte;
- {
- #ifdef _MSC_VER
- __declspec(align(16)) UInt8 unit_bytes[16];
- __declspec(align(16)) UInt8 accumulated_counts_bytes[16];
- #else // _MSC_VER
- UInt8 unit_bytes[16] __attribute__ ((aligned (16)));
- UInt8 accumulated_counts_bytes[16] __attribute__ ((aligned (16)));
- #endif // _MSC_VER
- accumulated_counts = _mm_slli_si128(accumulated_counts, 1);
- _mm_store_si128(reinterpret_cast<__m128i *>(unit_bytes), unit);
- _mm_store_si128(reinterpret_cast<__m128i *>(accumulated_counts_bytes),
- accumulated_counts);
-
- bit_id += skip;
- byte = unit_bytes[skip / 8];
- i -= accumulated_counts_bytes[skip / 8];
- }
-
- return bit_id + SELECT_TABLE[i][byte];
-}
- #endif // MARISA_USE_SSE2
-#endif // MARISA_WORD_SIZE == 64
-
-} // namespace
-
-#if MARISA_WORD_SIZE == 64
-
-std::size_t BitVector::rank1(std::size_t i) const {
- MARISA_DEBUG_IF(ranks_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i > size_, MARISA_BOUND_ERROR);
-
- const RankIndex &rank = ranks_[i / 512];
- std::size_t offset = rank.abs();
- switch ((i / 64) % 8) {
- case 1: {
- offset += rank.rel1();
- break;
- }
- case 2: {
- offset += rank.rel2();
- break;
- }
- case 3: {
- offset += rank.rel3();
- break;
- }
- case 4: {
- offset += rank.rel4();
- break;
- }
- case 5: {
- offset += rank.rel5();
- break;
- }
- case 6: {
- offset += rank.rel6();
- break;
- }
- case 7: {
- offset += rank.rel7();
- break;
- }
- }
- offset += PopCount::count(units_[i / 64] & ((1ULL << (i % 64)) - 1));
- return offset;
-}
-
-std::size_t BitVector::select0(std::size_t i) const {
- MARISA_DEBUG_IF(select0s_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i >= num_0s(), MARISA_BOUND_ERROR);
-
- const std::size_t select_id = i / 512;
- MARISA_DEBUG_IF((select_id + 1) >= select0s_.size(), MARISA_BOUND_ERROR);
- if ((i % 512) == 0) {
- return select0s_[select_id];
- }
- std::size_t begin = select0s_[select_id] / 512;
- std::size_t end = (select0s_[select_id + 1] + 511) / 512;
- if (begin + 10 >= end) {
- while (i >= ((begin + 1) * 512) - ranks_[begin + 1].abs()) {
- ++begin;
- }
- } else {
- while (begin + 1 < end) {
- const std::size_t middle = (begin + end) / 2;
- if (i < (middle * 512) - ranks_[middle].abs()) {
- end = middle;
- } else {
- begin = middle;
- }
- }
- }
- const std::size_t rank_id = begin;
- i -= (rank_id * 512) - ranks_[rank_id].abs();
-
- const RankIndex &rank = ranks_[rank_id];
- std::size_t unit_id = rank_id * 8;
- if (i < (256U - rank.rel4())) {
- if (i < (128U - rank.rel2())) {
- if (i >= (64U - rank.rel1())) {
- unit_id += 1;
- i -= 64 - rank.rel1();
- }
- } else if (i < (192U - rank.rel3())) {
- unit_id += 2;
- i -= 128 - rank.rel2();
- } else {
- unit_id += 3;
- i -= 192 - rank.rel3();
- }
- } else if (i < (384U - rank.rel6())) {
- if (i < (320U - rank.rel5())) {
- unit_id += 4;
- i -= 256 - rank.rel4();
- } else {
- unit_id += 5;
- i -= 320 - rank.rel5();
- }
- } else if (i < (448U - rank.rel7())) {
- unit_id += 6;
- i -= 384 - rank.rel6();
- } else {
- unit_id += 7;
- i -= 448 - rank.rel7();
- }
-
- return select_bit(i, unit_id * 64, ~units_[unit_id]);
-}
-
-std::size_t BitVector::select1(std::size_t i) const {
- MARISA_DEBUG_IF(select1s_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i >= num_1s(), MARISA_BOUND_ERROR);
-
- const std::size_t select_id = i / 512;
- MARISA_DEBUG_IF((select_id + 1) >= select1s_.size(), MARISA_BOUND_ERROR);
- if ((i % 512) == 0) {
- return select1s_[select_id];
- }
- std::size_t begin = select1s_[select_id] / 512;
- std::size_t end = (select1s_[select_id + 1] + 511) / 512;
- if (begin + 10 >= end) {
- while (i >= ranks_[begin + 1].abs()) {
- ++begin;
- }
- } else {
- while (begin + 1 < end) {
- const std::size_t middle = (begin + end) / 2;
- if (i < ranks_[middle].abs()) {
- end = middle;
- } else {
- begin = middle;
- }
- }
- }
- const std::size_t rank_id = begin;
- i -= ranks_[rank_id].abs();
-
- const RankIndex &rank = ranks_[rank_id];
- std::size_t unit_id = rank_id * 8;
- if (i < rank.rel4()) {
- if (i < rank.rel2()) {
- if (i >= rank.rel1()) {
- unit_id += 1;
- i -= rank.rel1();
- }
- } else if (i < rank.rel3()) {
- unit_id += 2;
- i -= rank.rel2();
- } else {
- unit_id += 3;
- i -= rank.rel3();
- }
- } else if (i < rank.rel6()) {
- if (i < rank.rel5()) {
- unit_id += 4;
- i -= rank.rel4();
- } else {
- unit_id += 5;
- i -= rank.rel5();
- }
- } else if (i < rank.rel7()) {
- unit_id += 6;
- i -= rank.rel6();
- } else {
- unit_id += 7;
- i -= rank.rel7();
- }
-
- return select_bit(i, unit_id * 64, units_[unit_id]);
-}
-
-#else // MARISA_WORD_SIZE == 64
-
-std::size_t BitVector::rank1(std::size_t i) const {
- MARISA_DEBUG_IF(ranks_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i > size_, MARISA_BOUND_ERROR);
-
- const RankIndex &rank = ranks_[i / 512];
- std::size_t offset = rank.abs();
- switch ((i / 64) % 8) {
- case 1: {
- offset += rank.rel1();
- break;
- }
- case 2: {
- offset += rank.rel2();
- break;
- }
- case 3: {
- offset += rank.rel3();
- break;
- }
- case 4: {
- offset += rank.rel4();
- break;
- }
- case 5: {
- offset += rank.rel5();
- break;
- }
- case 6: {
- offset += rank.rel6();
- break;
- }
- case 7: {
- offset += rank.rel7();
- break;
- }
- }
- if (((i / 32) & 1) == 1) {
- offset += PopCount::count(units_[(i / 32) - 1]);
- }
- offset += PopCount::count(units_[i / 32] & ((1U << (i % 32)) - 1));
- return offset;
-}
-
-std::size_t BitVector::select0(std::size_t i) const {
- MARISA_DEBUG_IF(select0s_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i >= num_0s(), MARISA_BOUND_ERROR);
-
- const std::size_t select_id = i / 512;
- MARISA_DEBUG_IF((select_id + 1) >= select0s_.size(), MARISA_BOUND_ERROR);
- if ((i % 512) == 0) {
- return select0s_[select_id];
- }
- std::size_t begin = select0s_[select_id] / 512;
- std::size_t end = (select0s_[select_id + 1] + 511) / 512;
- if (begin + 10 >= end) {
- while (i >= ((begin + 1) * 512) - ranks_[begin + 1].abs()) {
- ++begin;
- }
- } else {
- while (begin + 1 < end) {
- const std::size_t middle = (begin + end) / 2;
- if (i < (middle * 512) - ranks_[middle].abs()) {
- end = middle;
- } else {
- begin = middle;
- }
- }
- }
- const std::size_t rank_id = begin;
- i -= (rank_id * 512) - ranks_[rank_id].abs();
-
- const RankIndex &rank = ranks_[rank_id];
- std::size_t unit_id = rank_id * 16;
- if (i < (256U - rank.rel4())) {
- if (i < (128U - rank.rel2())) {
- if (i >= (64U - rank.rel1())) {
- unit_id += 2;
- i -= 64 - rank.rel1();
- }
- } else if (i < (192U - rank.rel3())) {
- unit_id += 4;
- i -= 128 - rank.rel2();
- } else {
- unit_id += 6;
- i -= 192 - rank.rel3();
- }
- } else if (i < (384U - rank.rel6())) {
- if (i < (320U - rank.rel5())) {
- unit_id += 8;
- i -= 256 - rank.rel4();
- } else {
- unit_id += 10;
- i -= 320 - rank.rel5();
- }
- } else if (i < (448U - rank.rel7())) {
- unit_id += 12;
- i -= 384 - rank.rel6();
- } else {
- unit_id += 14;
- i -= 448 - rank.rel7();
- }
-
-#ifdef MARISA_USE_SSE2
- return select_bit(i, unit_id * 32, ~units_[unit_id], ~units_[unit_id + 1]);
-#else // MARISA_USE_SSE2
- UInt32 unit = ~units_[unit_id];
- PopCount count(unit);
- if (i >= count.lo32()) {
- ++unit_id;
- i -= count.lo32();
- unit = ~units_[unit_id];
- count = PopCount(unit);
- }
-
- std::size_t bit_id = unit_id * 32;
- if (i < count.lo16()) {
- if (i >= count.lo8()) {
- bit_id += 8;
- unit >>= 8;
- i -= count.lo8();
- }
- } else if (i < count.lo24()) {
- bit_id += 16;
- unit >>= 16;
- i -= count.lo16();
- } else {
- bit_id += 24;
- unit >>= 24;
- i -= count.lo24();
- }
- return bit_id + SELECT_TABLE[i][unit & 0xFF];
-#endif // MARISA_USE_SSE2
-}
-
-std::size_t BitVector::select1(std::size_t i) const {
- MARISA_DEBUG_IF(select1s_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i >= num_1s(), MARISA_BOUND_ERROR);
-
- const std::size_t select_id = i / 512;
- MARISA_DEBUG_IF((select_id + 1) >= select1s_.size(), MARISA_BOUND_ERROR);
- if ((i % 512) == 0) {
- return select1s_[select_id];
- }
- std::size_t begin = select1s_[select_id] / 512;
- std::size_t end = (select1s_[select_id + 1] + 511) / 512;
- if (begin + 10 >= end) {
- while (i >= ranks_[begin + 1].abs()) {
- ++begin;
- }
- } else {
- while (begin + 1 < end) {
- const std::size_t middle = (begin + end) / 2;
- if (i < ranks_[middle].abs()) {
- end = middle;
- } else {
- begin = middle;
- }
- }
- }
- const std::size_t rank_id = begin;
- i -= ranks_[rank_id].abs();
-
- const RankIndex &rank = ranks_[rank_id];
- std::size_t unit_id = rank_id * 16;
- if (i < rank.rel4()) {
- if (i < rank.rel2()) {
- if (i >= rank.rel1()) {
- unit_id += 2;
- i -= rank.rel1();
- }
- } else if (i < rank.rel3()) {
- unit_id += 4;
- i -= rank.rel2();
- } else {
- unit_id += 6;
- i -= rank.rel3();
- }
- } else if (i < rank.rel6()) {
- if (i < rank.rel5()) {
- unit_id += 8;
- i -= rank.rel4();
- } else {
- unit_id += 10;
- i -= rank.rel5();
- }
- } else if (i < rank.rel7()) {
- unit_id += 12;
- i -= rank.rel6();
- } else {
- unit_id += 14;
- i -= rank.rel7();
- }
-
-#ifdef MARISA_USE_SSE2
- return select_bit(i, unit_id * 32, units_[unit_id], units_[unit_id + 1]);
-#else // MARISA_USE_SSE2
- UInt32 unit = units_[unit_id];
- PopCount count(unit);
- if (i >= count.lo32()) {
- ++unit_id;
- i -= count.lo32();
- unit = units_[unit_id];
- count = PopCount(unit);
- }
-
- std::size_t bit_id = unit_id * 32;
- if (i < count.lo16()) {
- if (i >= count.lo8()) {
- bit_id += 8;
- unit >>= 8;
- i -= count.lo8();
- }
- } else if (i < count.lo24()) {
- bit_id += 16;
- unit >>= 16;
- i -= count.lo16();
- } else {
- bit_id += 24;
- unit >>= 24;
- i -= count.lo24();
- }
- return bit_id + SELECT_TABLE[i][unit & 0xFF];
-#endif // MARISA_USE_SSE2
-}
-
-#endif // MARISA_WORD_SIZE == 64
-
-void BitVector::build_index(const BitVector &bv,
- bool enables_select0, bool enables_select1) {
- ranks_.resize((bv.size() / 512) + (((bv.size() % 512) != 0) ? 1 : 0) + 1);
-
- std::size_t num_0s = 0;
- std::size_t num_1s = 0;
-
- for (std::size_t i = 0; i < bv.size(); ++i) {
- if ((i % 64) == 0) {
- const std::size_t rank_id = i / 512;
- switch ((i / 64) % 8) {
- case 0: {
- ranks_[rank_id].set_abs(num_1s);
- break;
- }
- case 1: {
- ranks_[rank_id].set_rel1(num_1s - ranks_[rank_id].abs());
- break;
- }
- case 2: {
- ranks_[rank_id].set_rel2(num_1s - ranks_[rank_id].abs());
- break;
- }
- case 3: {
- ranks_[rank_id].set_rel3(num_1s - ranks_[rank_id].abs());
- break;
- }
- case 4: {
- ranks_[rank_id].set_rel4(num_1s - ranks_[rank_id].abs());
- break;
- }
- case 5: {
- ranks_[rank_id].set_rel5(num_1s - ranks_[rank_id].abs());
- break;
- }
- case 6: {
- ranks_[rank_id].set_rel6(num_1s - ranks_[rank_id].abs());
- break;
- }
- case 7: {
- ranks_[rank_id].set_rel7(num_1s - ranks_[rank_id].abs());
- break;
- }
- }
- }
-
- if (bv[i]) {
- if (enables_select1 && ((num_1s % 512) == 0)) {
- select1s_.push_back(static_cast<UInt32>(i));
- }
- ++num_1s;
- } else {
- if (enables_select0 && ((num_0s % 512) == 0)) {
- select0s_.push_back(static_cast<UInt32>(i));
- }
- ++num_0s;
- }
- }
-
- if ((bv.size() % 512) != 0) {
- const std::size_t rank_id = (bv.size() - 1) / 512;
- switch (((bv.size() - 1) / 64) % 8) {
- case 0: {
- ranks_[rank_id].set_rel1(num_1s - ranks_[rank_id].abs());
- }
- case 1: {
- ranks_[rank_id].set_rel2(num_1s - ranks_[rank_id].abs());
- }
- case 2: {
- ranks_[rank_id].set_rel3(num_1s - ranks_[rank_id].abs());
- }
- case 3: {
- ranks_[rank_id].set_rel4(num_1s - ranks_[rank_id].abs());
- }
- case 4: {
- ranks_[rank_id].set_rel5(num_1s - ranks_[rank_id].abs());
- }
- case 5: {
- ranks_[rank_id].set_rel6(num_1s - ranks_[rank_id].abs());
- }
- case 6: {
- ranks_[rank_id].set_rel7(num_1s - ranks_[rank_id].abs());
- break;
- }
- }
- }
-
- size_ = bv.size();
- num_1s_ = bv.num_1s();
-
- ranks_.back().set_abs(num_1s);
- if (enables_select0) {
- select0s_.push_back(static_cast<UInt32>(bv.size()));
- select0s_.shrink();
- }
- if (enables_select1) {
- select1s_.push_back(static_cast<UInt32>(bv.size()));
- select1s_.shrink();
- }
-}
-
-} // namespace vector
-} // namespace grimoire
-} // namespace marisa
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_VECTOR_BIT_VECTOR_H_
-#define MARISA_GRIMOIRE_VECTOR_BIT_VECTOR_H_
-
-#include "marisa/grimoire/vector/rank-index.h"
-#include "marisa/grimoire/vector/vector.h"
-
-namespace marisa {
-namespace grimoire {
-namespace vector {
-
-class BitVector {
- public:
-#if MARISA_WORD_SIZE == 64
- typedef UInt64 Unit;
-#else // MARISA_WORD_SIZE == 64
- typedef UInt32 Unit;
-#endif // MARISA_WORD_SIZE == 64
-
- BitVector()
- : units_(), size_(0), num_1s_(0), ranks_(), select0s_(), select1s_() {}
-
- void build(bool enables_select0, bool enables_select1) {
- BitVector temp;
- temp.build_index(*this, enables_select0, enables_select1);
- units_.shrink();
- temp.units_.swap(units_);
- swap(temp);
- }
-
- void map(Mapper &mapper) {
- BitVector temp;
- temp.map_(mapper);
- swap(temp);
- }
- void read(Reader &reader) {
- BitVector temp;
- temp.read_(reader);
- swap(temp);
- }
- void write(Writer &writer) const {
- write_(writer);
- }
-
- void disable_select0() {
- select0s_.clear();
- }
- void disable_select1() {
- select1s_.clear();
- }
-
- void push_back(bool bit) {
- MARISA_THROW_IF(size_ == MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- if (size_ == (MARISA_WORD_SIZE * units_.size())) {
- units_.resize(units_.size() + (64 / MARISA_WORD_SIZE), 0);
- }
- if (bit) {
- units_[size_ / MARISA_WORD_SIZE] |=
- (Unit)1 << (size_ % MARISA_WORD_SIZE);
- ++num_1s_;
- }
- ++size_;
- }
-
- bool operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
- return (units_[i / MARISA_WORD_SIZE]
- & ((Unit)1 << (i % MARISA_WORD_SIZE))) != 0;
- }
-
- std::size_t rank0(std::size_t i) const {
- MARISA_DEBUG_IF(ranks_.empty(), MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i > size_, MARISA_BOUND_ERROR);
- return i - rank1(i);
- }
- std::size_t rank1(std::size_t i) const;
-
- std::size_t select0(std::size_t i) const;
- std::size_t select1(std::size_t i) const;
-
- std::size_t num_0s() const {
- return size_ - num_1s_;
- }
- std::size_t num_1s() const {
- return num_1s_;
- }
-
- bool empty() const {
- return size_ == 0;
- }
- std::size_t size() const {
- return size_;
- }
- std::size_t total_size() const {
- return units_.total_size() + ranks_.total_size()
- + select0s_.total_size() + select1s_.total_size();
- }
- std::size_t io_size() const {
- return units_.io_size() + (sizeof(UInt32) * 2) + ranks_.io_size()
- + select0s_.io_size() + select1s_.io_size();
- }
-
- void clear() {
- BitVector().swap(*this);
- }
- void swap(BitVector &rhs) {
- units_.swap(rhs.units_);
- marisa::swap(size_, rhs.size_);
- marisa::swap(num_1s_, rhs.num_1s_);
- ranks_.swap(rhs.ranks_);
- select0s_.swap(rhs.select0s_);
- select1s_.swap(rhs.select1s_);
- }
-
- private:
- Vector<Unit> units_;
- std::size_t size_;
- std::size_t num_1s_;
- Vector<RankIndex> ranks_;
- Vector<UInt32> select0s_;
- Vector<UInt32> select1s_;
-
- void build_index(const BitVector &bv,
- bool enables_select0, bool enables_select1);
-
- void map_(Mapper &mapper) {
- units_.map(mapper);
- {
- UInt32 temp_size;
- mapper.map(&temp_size);
- size_ = temp_size;
- }
- {
- UInt32 temp_num_1s;
- mapper.map(&temp_num_1s);
- MARISA_THROW_IF(temp_num_1s > size_, MARISA_FORMAT_ERROR);
- num_1s_ = temp_num_1s;
- }
- ranks_.map(mapper);
- select0s_.map(mapper);
- select1s_.map(mapper);
- }
-
- void read_(Reader &reader) {
- units_.read(reader);
- {
- UInt32 temp_size;
- reader.read(&temp_size);
- size_ = temp_size;
- }
- {
- UInt32 temp_num_1s;
- reader.read(&temp_num_1s);
- MARISA_THROW_IF(temp_num_1s > size_, MARISA_FORMAT_ERROR);
- num_1s_ = temp_num_1s;
- }
- ranks_.read(reader);
- select0s_.read(reader);
- select1s_.read(reader);
- }
-
- void write_(Writer &writer) const {
- units_.write(writer);
- writer.write((UInt32)size_);
- writer.write((UInt32)num_1s_);
- ranks_.write(writer);
- select0s_.write(writer);
- select1s_.write(writer);
- }
-
- // Disallows copy and assignment.
- BitVector(const BitVector &);
- BitVector &operator=(const BitVector &);
-};
-
-} // namespace vector
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_VECTOR_BIT_VECTOR_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_VECTOR_FLAT_VECTOR_H_
-#define MARISA_GRIMOIRE_VECTOR_FLAT_VECTOR_H_
-
-#include "marisa/grimoire/vector/vector.h"
-
-namespace marisa {
-namespace grimoire {
-namespace vector {
-
-class FlatVector {
- public:
-#if MARISA_WORD_SIZE == 64
- typedef UInt64 Unit;
-#else // MARISA_WORD_SIZE == 64
- typedef UInt32 Unit;
-#endif // MARISA_WORD_SIZE == 64
-
- FlatVector() : units_(), value_size_(0), mask_(0), size_(0) {}
-
- void build(const Vector<UInt32> &values) {
- FlatVector temp;
- temp.build_(values);
- swap(temp);
- }
-
- void map(Mapper &mapper) {
- FlatVector temp;
- temp.map_(mapper);
- swap(temp);
- }
- void read(Reader &reader) {
- FlatVector temp;
- temp.read_(reader);
- swap(temp);
- }
- void write(Writer &writer) const {
- write_(writer);
- }
-
- UInt32 operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
-
- const std::size_t pos = i * value_size_;
- const std::size_t unit_id = pos / MARISA_WORD_SIZE;
- const std::size_t unit_offset = pos % MARISA_WORD_SIZE;
-
- if ((unit_offset + value_size_) <= MARISA_WORD_SIZE) {
- return (UInt32)(units_[unit_id] >> unit_offset) & mask_;
- } else {
- return (UInt32)((units_[unit_id] >> unit_offset)
- | (units_[unit_id + 1] << (MARISA_WORD_SIZE - unit_offset))) & mask_;
- }
- }
-
- std::size_t value_size() const {
- return value_size_;
- }
- UInt32 mask() const {
- return mask_;
- }
-
- bool empty() const {
- return size_ == 0;
- }
- std::size_t size() const {
- return size_;
- }
- std::size_t total_size() const {
- return units_.total_size();
- }
- std::size_t io_size() const {
- return units_.io_size() + (sizeof(UInt32) * 2) + sizeof(UInt64);
- }
-
- void clear() {
- FlatVector().swap(*this);
- }
- void swap(FlatVector &rhs) {
- units_.swap(rhs.units_);
- marisa::swap(value_size_, rhs.value_size_);
- marisa::swap(mask_, rhs.mask_);
- marisa::swap(size_, rhs.size_);
- }
-
- private:
- Vector<Unit> units_;
- std::size_t value_size_;
- UInt32 mask_;
- std::size_t size_;
-
- void build_(const Vector<UInt32> &values) {
- UInt32 max_value = 0;
- for (std::size_t i = 0; i < values.size(); ++i) {
- if (values[i] > max_value) {
- max_value = values[i];
- }
- }
-
- std::size_t value_size = 0;
- while (max_value != 0) {
- ++value_size;
- max_value >>= 1;
- }
-
- std::size_t num_units = values.empty() ? 0 : (64 / MARISA_WORD_SIZE);
- if (value_size != 0) {
- num_units = (std::size_t)(
- (((UInt64)value_size * values.size()) + (MARISA_WORD_SIZE - 1))
- / MARISA_WORD_SIZE);
- num_units += num_units % (64 / MARISA_WORD_SIZE);
- }
-
- units_.resize(num_units);
- if (num_units > 0) {
- units_.back() = 0;
- }
-
- value_size_ = value_size;
- if (value_size != 0) {
- mask_ = MARISA_UINT32_MAX >> (32 - value_size);
- }
- size_ = values.size();
-
- for (std::size_t i = 0; i < values.size(); ++i) {
- set(i, values[i]);
- }
- }
-
- void map_(Mapper &mapper) {
- units_.map(mapper);
- {
- UInt32 temp_value_size;
- mapper.map(&temp_value_size);
- MARISA_THROW_IF(temp_value_size > 32, MARISA_FORMAT_ERROR);
- value_size_ = temp_value_size;
- }
- {
- UInt32 temp_mask;
- mapper.map(&temp_mask);
- mask_ = temp_mask;
- }
- {
- UInt64 temp_size;
- mapper.map(&temp_size);
- MARISA_THROW_IF(temp_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- size_ = (std::size_t)temp_size;
- }
- }
-
- void read_(Reader &reader) {
- units_.read(reader);
- {
- UInt32 temp_value_size;
- reader.read(&temp_value_size);
- MARISA_THROW_IF(temp_value_size > 32, MARISA_FORMAT_ERROR);
- value_size_ = temp_value_size;
- }
- {
- UInt32 temp_mask;
- reader.read(&temp_mask);
- mask_ = temp_mask;
- }
- {
- UInt64 temp_size;
- reader.read(&temp_size);
- MARISA_THROW_IF(temp_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- size_ = (std::size_t)temp_size;
- }
- }
-
- void write_(Writer &writer) const {
- units_.write(writer);
- writer.write((UInt32)value_size_);
- writer.write((UInt32)mask_);
- writer.write((UInt64)size_);
- }
-
- void set(std::size_t i, UInt32 value) {
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
- MARISA_DEBUG_IF(value > mask_, MARISA_RANGE_ERROR);
-
- const std::size_t pos = i * value_size_;
- const std::size_t unit_id = pos / MARISA_WORD_SIZE;
- const std::size_t unit_offset = pos % MARISA_WORD_SIZE;
-
- units_[unit_id] &= ~((Unit)mask_ << unit_offset);
- units_[unit_id] |= (Unit)(value & mask_) << unit_offset;
- if ((unit_offset + value_size_) > MARISA_WORD_SIZE) {
- units_[unit_id + 1] &=
- ~((Unit)mask_ >> (MARISA_WORD_SIZE - unit_offset));
- units_[unit_id + 1] |=
- (Unit)(value & mask_) >> (MARISA_WORD_SIZE - unit_offset);
- }
- }
-
- // Disallows copy and assignment.
- FlatVector(const FlatVector &);
- FlatVector &operator=(const FlatVector &);
-};
-
-} // namespace vector
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_VECTOR_FLAT_VECTOR_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_VECTOR_POP_COUNT_H_
-#define MARISA_GRIMOIRE_VECTOR_POP_COUNT_H_
-
-#include "marisa/grimoire/intrin.h"
-
-namespace marisa {
-namespace grimoire {
-namespace vector {
-
-#if MARISA_WORD_SIZE == 64
-
-class PopCount {
- public:
- explicit PopCount(UInt64 x) : value_() {
- x = (x & 0x5555555555555555ULL) + ((x & 0xAAAAAAAAAAAAAAAAULL) >> 1);
- x = (x & 0x3333333333333333ULL) + ((x & 0xCCCCCCCCCCCCCCCCULL) >> 2);
- x = (x & 0x0F0F0F0F0F0F0F0FULL) + ((x & 0xF0F0F0F0F0F0F0F0ULL) >> 4);
- x *= 0x0101010101010101ULL;
- value_ = x;
- }
-
- std::size_t lo8() const {
- return (std::size_t)(value_ & 0xFFU);
- }
- std::size_t lo16() const {
- return (std::size_t)((value_ >> 8) & 0xFFU);
- }
- std::size_t lo24() const {
- return (std::size_t)((value_ >> 16) & 0xFFU);
- }
- std::size_t lo32() const {
- return (std::size_t)((value_ >> 24) & 0xFFU);
- }
- std::size_t lo40() const {
- return (std::size_t)((value_ >> 32) & 0xFFU);
- }
- std::size_t lo48() const {
- return (std::size_t)((value_ >> 40) & 0xFFU);
- }
- std::size_t lo56() const {
- return (std::size_t)((value_ >> 48) & 0xFFU);
- }
- std::size_t lo64() const {
- return (std::size_t)((value_ >> 56) & 0xFFU);
- }
-
- static std::size_t count(UInt64 x) {
-#if defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
- #ifdef _MSC_VER
- return __popcnt64(x);
- #else // _MSC_VER
- return _mm_popcnt_u64(x);
- #endif // _MSC_VER
-#else // defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
- return PopCount(x).lo64();
-#endif // defined(MARISA_X64) && defined(MARISA_USE_POPCNT)
- }
-
- private:
- UInt64 value_;
-};
-
-#else // MARISA_WORD_SIZE == 64
-
-class PopCount {
- public:
- explicit PopCount(UInt32 x) : value_() {
- x = (x & 0x55555555U) + ((x & 0xAAAAAAAAU) >> 1);
- x = (x & 0x33333333U) + ((x & 0xCCCCCCCCU) >> 2);
- x = (x & 0x0F0F0F0FU) + ((x & 0xF0F0F0F0U) >> 4);
- x *= 0x01010101U;
- value_ = x;
- }
-
- std::size_t lo8() const {
- return value_ & 0xFFU;
- }
- std::size_t lo16() const {
- return (value_ >> 8) & 0xFFU;
- }
- std::size_t lo24() const {
- return (value_ >> 16) & 0xFFU;
- }
- std::size_t lo32() const {
- return (value_ >> 24) & 0xFFU;
- }
-
- static std::size_t count(UInt32 x) {
-#ifdef MARISA_USE_POPCNT
- #ifdef _MSC_VER
- return __popcnt(x);
- #else // _MSC_VER
- return _mm_popcnt_u32(x);
- #endif // _MSC_VER
-#else // MARISA_USE_POPCNT
- return PopCount(x).lo32();
-#endif // MARISA_USE_POPCNT
- }
-
- private:
- UInt32 value_;
-};
-
-#endif // MARISA_WORD_SIZE == 64
-
-} // namespace vector
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_VECTOR_POP_COUNT_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_VECTOR_RANK_INDEX_H_
-#define MARISA_GRIMOIRE_VECTOR_RANK_INDEX_H_
-
-#include "marisa/base.h"
-
-namespace marisa {
-namespace grimoire {
-namespace vector {
-
-class RankIndex {
- public:
- RankIndex() : abs_(0), rel_lo_(0), rel_hi_(0) {}
-
- void set_abs(std::size_t value) {
- MARISA_DEBUG_IF(value > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
- abs_ = (UInt32)value;
- }
- void set_rel1(std::size_t value) {
- MARISA_DEBUG_IF(value > 64, MARISA_RANGE_ERROR);
- rel_lo_ = (UInt32)((rel_lo_ & ~0x7FU) | (value & 0x7FU));
- }
- void set_rel2(std::size_t value) {
- MARISA_DEBUG_IF(value > 128, MARISA_RANGE_ERROR);
- rel_lo_ = (UInt32)((rel_lo_ & ~(0xFFU << 7)) | ((value & 0xFFU) << 7));
- }
- void set_rel3(std::size_t value) {
- MARISA_DEBUG_IF(value > 192, MARISA_RANGE_ERROR);
- rel_lo_ = (UInt32)((rel_lo_ & ~(0xFFU << 15)) | ((value & 0xFFU) << 15));
- }
- void set_rel4(std::size_t value) {
- MARISA_DEBUG_IF(value > 256, MARISA_RANGE_ERROR);
- rel_lo_ = (UInt32)((rel_lo_ & ~(0x1FFU << 23)) | ((value & 0x1FFU) << 23));
- }
- void set_rel5(std::size_t value) {
- MARISA_DEBUG_IF(value > 320, MARISA_RANGE_ERROR);
- rel_hi_ = (UInt32)((rel_hi_ & ~0x1FFU) | (value & 0x1FFU));
- }
- void set_rel6(std::size_t value) {
- MARISA_DEBUG_IF(value > 384, MARISA_RANGE_ERROR);
- rel_hi_ = (UInt32)((rel_hi_ & ~(0x1FFU << 9)) | ((value & 0x1FFU) << 9));
- }
- void set_rel7(std::size_t value) {
- MARISA_DEBUG_IF(value > 448, MARISA_RANGE_ERROR);
- rel_hi_ = (UInt32)((rel_hi_ & ~(0x1FFU << 18)) | ((value & 0x1FFU) << 18));
- }
-
- std::size_t abs() const {
- return abs_;
- }
- std::size_t rel1() const {
- return rel_lo_ & 0x7FU;
- }
- std::size_t rel2() const {
- return (rel_lo_ >> 7) & 0xFFU;
- }
- std::size_t rel3() const {
- return (rel_lo_ >> 15) & 0xFFU;
- }
- std::size_t rel4() const {
- return (rel_lo_ >> 23) & 0x1FFU;
- }
- std::size_t rel5() const {
- return rel_hi_ & 0x1FFU;
- }
- std::size_t rel6() const {
- return (rel_hi_ >> 9) & 0x1FFU;
- }
- std::size_t rel7() const {
- return (rel_hi_ >> 18) & 0x1FFU;
- }
-
- private:
- UInt32 abs_;
- UInt32 rel_lo_;
- UInt32 rel_hi_;
-};
-
-} // namespace vector
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_VECTOR_RANK_INDEX_H_
+++ /dev/null
-#ifndef MARISA_GRIMOIRE_VECTOR_VECTOR_H_
-#define MARISA_GRIMOIRE_VECTOR_VECTOR_H_
-
-#include <new>
-
-#include "marisa/grimoire/io.h"
-
-namespace marisa {
-namespace grimoire {
-namespace vector {
-
-template <typename T>
-class Vector {
- public:
- Vector()
- : buf_(), objs_(NULL), const_objs_(NULL),
- size_(0), capacity_(0), fixed_(false) {}
- ~Vector() {
- if (objs_ != NULL) {
- for (std::size_t i = 0; i < size_; ++i) {
- objs_[i].~T();
- }
- }
- }
-
- void map(Mapper &mapper) {
- Vector temp;
- temp.map_(mapper);
- swap(temp);
- }
-
- void read(Reader &reader) {
- Vector temp;
- temp.read_(reader);
- swap(temp);
- }
-
- void write(Writer &writer) const {
- write_(writer);
- }
-
- void push_back(const T &x) {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(size_ == max_size(), MARISA_SIZE_ERROR);
- reserve(size_ + 1);
- new (&objs_[size_]) T(x);
- ++size_;
- }
-
- void pop_back() {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(size_ == 0, MARISA_STATE_ERROR);
- objs_[--size_].~T();
- }
-
- // resize() assumes that T's placement new does not throw an exception.
- void resize(std::size_t size) {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- reserve(size);
- for (std::size_t i = size_; i < size; ++i) {
- new (&objs_[i]) T;
- }
- for (std::size_t i = size; i < size_; ++i) {
- objs_[i].~T();
- }
- size_ = size;
- }
-
- // resize() assumes that T's placement new does not throw an exception.
- void resize(std::size_t size, const T &x) {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- reserve(size);
- for (std::size_t i = size_; i < size; ++i) {
- new (&objs_[i]) T(x);
- }
- for (std::size_t i = size; i < size_; ++i) {
- objs_[i].~T();
- }
- size_ = size;
- }
-
- void reserve(std::size_t capacity) {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- if (capacity <= capacity_) {
- return;
- }
- MARISA_DEBUG_IF(capacity > max_size(), MARISA_SIZE_ERROR);
- std::size_t new_capacity = capacity;
- if (capacity_ > (capacity / 2)) {
- if (capacity_ > (max_size() / 2)) {
- new_capacity = max_size();
- } else {
- new_capacity = capacity_ * 2;
- }
- }
- realloc(new_capacity);
- }
-
- void shrink() {
- MARISA_THROW_IF(fixed_, MARISA_STATE_ERROR);
- if (size_ != capacity_) {
- realloc(size_);
- }
- }
-
- void fix() {
- MARISA_THROW_IF(fixed_, MARISA_STATE_ERROR);
- fixed_ = true;
- }
-
- const T *begin() const {
- return const_objs_;
- }
- const T *end() const {
- return const_objs_ + size_;
- }
- const T &operator[](std::size_t i) const {
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
- return const_objs_[i];
- }
- const T &front() const {
- MARISA_DEBUG_IF(size_ == 0, MARISA_STATE_ERROR);
- return const_objs_[0];
- }
- const T &back() const {
- MARISA_DEBUG_IF(size_ == 0, MARISA_STATE_ERROR);
- return const_objs_[size_ - 1];
- }
-
- T *begin() {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- return objs_;
- }
- T *end() {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- return objs_ + size_;
- }
- T &operator[](std::size_t i) {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(i >= size_, MARISA_BOUND_ERROR);
- return objs_[i];
- }
- T &front() {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(size_ == 0, MARISA_STATE_ERROR);
- return objs_[0];
- }
- T &back() {
- MARISA_DEBUG_IF(fixed_, MARISA_STATE_ERROR);
- MARISA_DEBUG_IF(size_ == 0, MARISA_STATE_ERROR);
- return objs_[size_ - 1];
- }
-
- std::size_t size() const {
- return size_;
- }
- std::size_t capacity() const {
- return capacity_;
- }
- bool fixed() const {
- return fixed_;
- }
-
- bool empty() const {
- return size_ == 0;
- }
- std::size_t total_size() const {
- return sizeof(T) * size_;
- }
- std::size_t io_size() const {
- return sizeof(UInt64) + ((total_size() + 7) & ~(std::size_t)0x07);
- }
-
- void clear() {
- Vector().swap(*this);
- }
- void swap(Vector &rhs) {
- buf_.swap(rhs.buf_);
- marisa::swap(objs_, rhs.objs_);
- marisa::swap(const_objs_, rhs.const_objs_);
- marisa::swap(size_, rhs.size_);
- marisa::swap(capacity_, rhs.capacity_);
- marisa::swap(fixed_, rhs.fixed_);
- }
-
- static std::size_t max_size() {
- return MARISA_SIZE_MAX / sizeof(T);
- }
-
- private:
- scoped_array<char> buf_;
- T *objs_;
- const T *const_objs_;
- std::size_t size_;
- std::size_t capacity_;
- bool fixed_;
-
- void map_(Mapper &mapper) {
- UInt64 total_size;
- mapper.map(&total_size);
- MARISA_THROW_IF(total_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- MARISA_THROW_IF((total_size % sizeof(T)) != 0, MARISA_FORMAT_ERROR);
- const std::size_t size = (std::size_t)(total_size / sizeof(T));
- mapper.map(&const_objs_, size);
- mapper.seek((std::size_t)((8 - (total_size % 8)) % 8));
- size_ = size;
- fix();
- }
- void read_(Reader &reader) {
- UInt64 total_size;
- reader.read(&total_size);
- MARISA_THROW_IF(total_size > MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- MARISA_THROW_IF((total_size % sizeof(T)) != 0, MARISA_FORMAT_ERROR);
- const std::size_t size = (std::size_t)(total_size / sizeof(T));
- resize(size);
- reader.read(objs_, size);
- reader.seek((std::size_t)((8 - (total_size % 8)) % 8));
- }
- void write_(Writer &writer) const {
- writer.write((UInt64)total_size());
- writer.write(const_objs_, size_);
- writer.seek((8 - (total_size() % 8)) % 8);
- }
-
- // realloc() assumes that T's placement new does not throw an exception.
- void realloc(std::size_t new_capacity) {
- MARISA_DEBUG_IF(new_capacity > max_size(), MARISA_SIZE_ERROR);
-
- scoped_array<char> new_buf(
- new (std::nothrow) char[sizeof(T) * new_capacity]);
- MARISA_DEBUG_IF(new_buf.get() == NULL, MARISA_MEMORY_ERROR);
- T *new_objs = reinterpret_cast<T *>(new_buf.get());
-
- for (std::size_t i = 0; i < size_; ++i) {
- new (&new_objs[i]) T(objs_[i]);
- }
- for (std::size_t i = 0; i < size_; ++i) {
- objs_[i].~T();
- }
-
- buf_.swap(new_buf);
- objs_ = new_objs;
- const_objs_ = new_objs;
- capacity_ = new_capacity;
- }
-
- // Disallows copy and assignment.
- Vector(const Vector &);
- Vector &operator=(const Vector &);
-};
-
-} // namespace vector
-} // namespace grimoire
-} // namespace marisa
-
-#endif // MARISA_GRIMOIRE_VECTOR_VECTOR_H_
+++ /dev/null
-#include <new>
-
-#include "marisa/keyset.h"
-
-namespace marisa {
-
-Keyset::Keyset()
- : base_blocks_(), base_blocks_size_(0), base_blocks_capacity_(0),
- extra_blocks_(), extra_blocks_size_(0), extra_blocks_capacity_(0),
- key_blocks_(), key_blocks_size_(0), key_blocks_capacity_(0),
- ptr_(NULL), avail_(0), size_(0), total_length_(0) {}
-
-void Keyset::push_back(const Key &key) {
- MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
-
- char * const key_ptr = reserve(key.length());
- for (std::size_t i = 0; i < key.length(); ++i) {
- key_ptr[i] = key[i];
- }
-
- Key &new_key = key_blocks_[size_ / KEY_BLOCK_SIZE][size_ % KEY_BLOCK_SIZE];
- new_key.set_str(key_ptr, key.length());
- new_key.set_id(key.id());
- ++size_;
- total_length_ += new_key.length();
-}
-
-void Keyset::push_back(const Key &key, char end_marker) {
- MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
-
- if ((size_ / KEY_BLOCK_SIZE) == key_blocks_size_) {
- append_key_block();
- }
-
- char * const key_ptr = reserve(key.length() + 1);
- for (std::size_t i = 0; i < key.length(); ++i) {
- key_ptr[i] = key[i];
- }
- key_ptr[key.length()] = end_marker;
-
- Key &new_key = key_blocks_[size_ / KEY_BLOCK_SIZE][size_ % KEY_BLOCK_SIZE];
- new_key.set_str(key_ptr, key.length());
- new_key.set_id(key.id());
- ++size_;
- total_length_ += new_key.length();
-}
-
-void Keyset::push_back(const char *str) {
- MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- MARISA_THROW_IF(str == NULL, MARISA_NULL_ERROR);
-
- std::size_t length = 0;
- while (str[length] != '\0') {
- ++length;
- }
- push_back(str, length);
-}
-
-void Keyset::push_back(const char *ptr, std::size_t length, float weight) {
- MARISA_DEBUG_IF(size_ == MARISA_SIZE_MAX, MARISA_SIZE_ERROR);
- MARISA_THROW_IF((ptr == NULL) && (length != 0), MARISA_NULL_ERROR);
- MARISA_THROW_IF(length > MARISA_UINT32_MAX, MARISA_SIZE_ERROR);
-
- char * const key_ptr = reserve(length);
- for (std::size_t i = 0; i < length; ++i) {
- key_ptr[i] = ptr[i];
- }
-
- Key &key = key_blocks_[size_ / KEY_BLOCK_SIZE][size_ % KEY_BLOCK_SIZE];
- key.set_str(key_ptr, length);
- key.set_weight(weight);
- ++size_;
- total_length_ += length;
-}
-
-void Keyset::reset() {
- base_blocks_size_ = 0;
- extra_blocks_size_ = 0;
- ptr_ = NULL;
- avail_ = 0;
- size_ = 0;
- total_length_ = 0;
-}
-
-void Keyset::clear() {
- Keyset().swap(*this);
-}
-
-void Keyset::swap(Keyset &rhs) {
- base_blocks_.swap(rhs.base_blocks_);
- marisa::swap(base_blocks_size_, rhs.base_blocks_size_);
- marisa::swap(base_blocks_capacity_, rhs.base_blocks_capacity_);
- extra_blocks_.swap(rhs.extra_blocks_);
- marisa::swap(extra_blocks_size_, rhs.extra_blocks_size_);
- marisa::swap(extra_blocks_capacity_, rhs.extra_blocks_capacity_);
- key_blocks_.swap(rhs.key_blocks_);
- marisa::swap(key_blocks_size_, rhs.key_blocks_size_);
- marisa::swap(key_blocks_capacity_, rhs.key_blocks_capacity_);
- marisa::swap(ptr_, rhs.ptr_);
- marisa::swap(avail_, rhs.avail_);
- marisa::swap(size_, rhs.size_);
- marisa::swap(total_length_, rhs.total_length_);
-}
-
-char *Keyset::reserve(std::size_t size) {
- if ((size_ / KEY_BLOCK_SIZE) == key_blocks_size_) {
- append_key_block();
- }
-
- if (size > EXTRA_BLOCK_SIZE) {
- append_extra_block(size);
- return extra_blocks_[extra_blocks_size_ - 1].get();
- } else {
- if (size > avail_) {
- append_base_block();
- }
- ptr_ += size;
- avail_ -= size;
- return ptr_ - size;
- }
-}
-
-void Keyset::append_base_block() {
- if (base_blocks_size_ == base_blocks_capacity_) {
- const std::size_t new_capacity =
- (base_blocks_size_ != 0) ? (base_blocks_size_ * 2) : 1;
- scoped_array<scoped_array<char> > new_blocks(
- new (std::nothrow) scoped_array<char>[new_capacity]);
- MARISA_THROW_IF(new_blocks.get() == NULL, MARISA_MEMORY_ERROR);
- for (std::size_t i = 0; i < base_blocks_size_; ++i) {
- base_blocks_[i].swap(new_blocks[i]);
- }
- base_blocks_.swap(new_blocks);
- base_blocks_capacity_ = new_capacity;
- }
- if (base_blocks_[base_blocks_size_].get() == NULL) {
- scoped_array<char> new_block(new (std::nothrow) char[BASE_BLOCK_SIZE]);
- MARISA_THROW_IF(new_block.get() == NULL, MARISA_MEMORY_ERROR);
- base_blocks_[base_blocks_size_].swap(new_block);
- }
- ptr_ = base_blocks_[base_blocks_size_++].get();
- avail_ = BASE_BLOCK_SIZE;
-}
-
-void Keyset::append_extra_block(std::size_t size) {
- if (extra_blocks_size_ == extra_blocks_capacity_) {
- const std::size_t new_capacity =
- (extra_blocks_size_ != 0) ? (extra_blocks_size_ * 2) : 1;
- scoped_array<scoped_array<char> > new_blocks(
- new (std::nothrow) scoped_array<char>[new_capacity]);
- MARISA_THROW_IF(new_blocks.get() == NULL, MARISA_MEMORY_ERROR);
- for (std::size_t i = 0; i < extra_blocks_size_; ++i) {
- extra_blocks_[i].swap(new_blocks[i]);
- }
- extra_blocks_.swap(new_blocks);
- extra_blocks_capacity_ = new_capacity;
- }
- scoped_array<char> new_block(new (std::nothrow) char[size]);
- MARISA_THROW_IF(new_block.get() == NULL, MARISA_MEMORY_ERROR);
- extra_blocks_[extra_blocks_size_++].swap(new_block);
-}
-
-void Keyset::append_key_block() {
- if (key_blocks_size_ == key_blocks_capacity_) {
- const std::size_t new_capacity =
- (key_blocks_size_ != 0) ? (key_blocks_size_ * 2) : 1;
- scoped_array<scoped_array<Key> > new_blocks(
- new (std::nothrow) scoped_array<Key>[new_capacity]);
- MARISA_THROW_IF(new_blocks.get() == NULL, MARISA_MEMORY_ERROR);
- for (std::size_t i = 0; i < key_blocks_size_; ++i) {
- key_blocks_[i].swap(new_blocks[i]);
- }
- key_blocks_.swap(new_blocks);
- key_blocks_capacity_ = new_capacity;
- }
- scoped_array<Key> new_block(new (std::nothrow) Key[KEY_BLOCK_SIZE]);
- MARISA_THROW_IF(new_block.get() == NULL, MARISA_MEMORY_ERROR);
- key_blocks_[key_blocks_size_++].swap(new_block);
-}
-
-} // namespace marisa
+++ /dev/null
-#include "marisa/stdio.h"
-#include "marisa/iostream.h"
-#include "marisa/trie.h"
-#include "marisa/grimoire/trie.h"
-
-namespace marisa {
-
-Trie::Trie() : trie_() {}
-
-Trie::~Trie() {}
-
-void Trie::build(Keyset &keyset, int config_flags) {
- scoped_ptr<grimoire::LoudsTrie> temp(new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- temp->build(keyset, config_flags);
- trie_.swap(temp);
-}
-
-void Trie::mmap(const char *filename) {
- MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
-
- scoped_ptr<grimoire::LoudsTrie> temp(new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- grimoire::Mapper mapper;
- mapper.open(filename);
- temp->map(mapper);
- trie_.swap(temp);
-}
-
-void Trie::map(const void *ptr, std::size_t size) {
- MARISA_THROW_IF((ptr == NULL) && (size != 0), MARISA_NULL_ERROR);
-
- scoped_ptr<grimoire::LoudsTrie> temp(new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- grimoire::Mapper mapper;
- mapper.open(ptr, size);
- temp->map(mapper);
- trie_.swap(temp);
-}
-
-void Trie::load(const char *filename) {
- MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
-
- scoped_ptr<grimoire::LoudsTrie> temp(new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- grimoire::Reader reader;
- reader.open(filename);
- temp->read(reader);
- trie_.swap(temp);
-}
-
-void Trie::read(int fd) {
- MARISA_THROW_IF(fd == -1, MARISA_CODE_ERROR);
-
- scoped_ptr<grimoire::LoudsTrie> temp(new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- grimoire::Reader reader;
- reader.open(fd);
- temp->read(reader);
- trie_.swap(temp);
-}
-
-void Trie::save(const char *filename) const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- MARISA_THROW_IF(filename == NULL, MARISA_NULL_ERROR);
-
- grimoire::Writer writer;
- writer.open(filename);
- trie_->write(writer);
-}
-
-void Trie::write(int fd) const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- MARISA_THROW_IF(fd == -1, MARISA_CODE_ERROR);
-
- grimoire::Writer writer;
- writer.open(fd);
- trie_->write(writer);
-}
-
-bool Trie::lookup(Agent &agent) const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- if (!agent.has_state()) {
- agent.init_state();
- }
- return trie_->lookup(agent);
-}
-
-void Trie::reverse_lookup(Agent &agent) const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- if (!agent.has_state()) {
- agent.init_state();
- }
- trie_->reverse_lookup(agent);
-}
-
-bool Trie::common_prefix_search(Agent &agent) const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- if (!agent.has_state()) {
- agent.init_state();
- }
- return trie_->common_prefix_search(agent);
-}
-
-bool Trie::predictive_search(Agent &agent) const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- if (!agent.has_state()) {
- agent.init_state();
- }
- return trie_->predictive_search(agent);
-}
-
-std::size_t Trie::num_tries() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->num_tries();
-}
-
-std::size_t Trie::num_keys() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->num_keys();
-}
-
-std::size_t Trie::num_nodes() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->num_nodes();
-}
-
-TailMode Trie::tail_mode() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->tail_mode();
-}
-
-NodeOrder Trie::node_order() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->node_order();
-}
-
-bool Trie::empty() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->empty();
-}
-
-std::size_t Trie::size() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->size();
-}
-
-std::size_t Trie::total_size() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->total_size();
-}
-
-std::size_t Trie::io_size() const {
- MARISA_THROW_IF(trie_.get() == NULL, MARISA_STATE_ERROR);
- return trie_->io_size();
-}
-
-void Trie::clear() {
- Trie().swap(*this);
-}
-
-void Trie::swap(Trie &rhs) {
- trie_.swap(rhs.trie_);
-}
-
-} // namespace marisa
-
-#include <iostream>
-
-namespace marisa {
-
-class TrieIO {
- public:
- static void fread(std::FILE *file, Trie *trie) {
- MARISA_THROW_IF(trie == NULL, MARISA_NULL_ERROR);
-
- scoped_ptr<grimoire::LoudsTrie> temp(
- new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- grimoire::Reader reader;
- reader.open(file);
- temp->read(reader);
- trie->trie_.swap(temp);
- }
- static void fwrite(std::FILE *file, const Trie &trie) {
- MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
- MARISA_THROW_IF(trie.trie_.get() == NULL, MARISA_STATE_ERROR);
- grimoire::Writer writer;
- writer.open(file);
- trie.trie_->write(writer);
- }
-
- static std::istream &read(std::istream &stream, Trie *trie) {
- MARISA_THROW_IF(trie == NULL, MARISA_NULL_ERROR);
-
- scoped_ptr<grimoire::LoudsTrie> temp(
- new (std::nothrow) grimoire::LoudsTrie);
- MARISA_THROW_IF(temp.get() == NULL, MARISA_MEMORY_ERROR);
-
- grimoire::Reader reader;
- reader.open(stream);
- temp->read(reader);
- trie->trie_.swap(temp);
- return stream;
- }
- static std::ostream &write(std::ostream &stream, const Trie &trie) {
- MARISA_THROW_IF(trie.trie_.get() == NULL, MARISA_STATE_ERROR);
- grimoire::Writer writer;
- writer.open(stream);
- trie.trie_->write(writer);
- return stream;
- }
-};
-
-void fread(std::FILE *file, Trie *trie) {
- MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
- MARISA_THROW_IF(trie == NULL, MARISA_NULL_ERROR);
- TrieIO::fread(file, trie);
-}
-
-void fwrite(std::FILE *file, const Trie &trie) {
- MARISA_THROW_IF(file == NULL, MARISA_NULL_ERROR);
- TrieIO::fwrite(file, trie);
-}
-
-std::istream &read(std::istream &stream, Trie *trie) {
- MARISA_THROW_IF(trie == NULL, MARISA_NULL_ERROR);
- return TrieIO::read(stream, trie);
-}
-
-std::ostream &write(std::ostream &stream, const Trie &trie) {
- return TrieIO::write(stream, trie);
-}
-
-std::istream &operator>>(std::istream &stream, Trie &trie) {
- return read(stream, &trie);
-}
-
-std::ostream &operator<<(std::ostream &stream, const Trie &trie) {
- return write(stream, trie);
-}
-
-} // namespace marisa
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ALLOCATORS_H_
-#define RAPIDJSON_ALLOCATORS_H_
-
-#include "rapidjson.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Allocator
-
-/*! \class rapidjson::Allocator
- \brief Concept for allocating, resizing and freeing memory block.
-
- Note that Malloc() and Realloc() are non-static but Free() is static.
-
- So if an allocator need to support Free(), it needs to put its pointer in
- the header of memory block.
-
-\code
-concept Allocator {
- static const bool kNeedFree; //!< Whether this allocator needs to call Free().
-
- // Allocate a memory block.
- // \param size of the memory block in bytes.
- // \returns pointer to the memory block.
- void* Malloc(size_t size);
-
- // Resize a memory block.
- // \param originalPtr The pointer to current memory block. Null pointer is permitted.
- // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
- // \param newSize the new size in bytes.
- void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
-
- // Free a memory block.
- // \param pointer to the memory block. Null pointer is permitted.
- static void Free(void *ptr);
-};
-\endcode
-*/
-
-///////////////////////////////////////////////////////////////////////////////
-// CrtAllocator
-
-//! C-runtime library allocator.
-/*! This class is just wrapper for standard C library memory routines.
- \note implements Allocator concept
-*/
-class CrtAllocator {
-public:
- static const bool kNeedFree = true;
- void* Malloc(size_t size) {
- if (size) // behavior of malloc(0) is implementation defined.
- return std::malloc(size);
- else
- return NULL; // standardize to returning NULL.
- }
- void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
- (void)originalSize;
- if (newSize == 0) {
- std::free(originalPtr);
- return NULL;
- }
- return std::realloc(originalPtr, newSize);
- }
- static void Free(void *ptr) { std::free(ptr); }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// MemoryPoolAllocator
-
-//! Default memory allocator used by the parser and DOM.
-/*! This allocator allocate memory blocks from pre-allocated memory chunks.
-
- It does not free memory blocks. And Realloc() only allocate new memory.
-
- The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
-
- User may also supply a buffer as the first chunk.
-
- If the user-buffer is full then additional chunks are allocated by BaseAllocator.
-
- The user-buffer is not deallocated by this allocator.
-
- \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
- \note implements Allocator concept
-*/
-template <typename BaseAllocator = CrtAllocator>
-class MemoryPoolAllocator {
-public:
- static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
-
- //! Constructor with chunkSize.
- /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
- \param baseAllocator The allocator for allocating memory chunks.
- */
- MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
- {
- }
-
- //! Constructor with user-supplied buffer.
- /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
-
- The user buffer will not be deallocated when this allocator is destructed.
-
- \param buffer User supplied buffer.
- \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
- \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
- \param baseAllocator The allocator for allocating memory chunks.
- */
- MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
- {
- RAPIDJSON_ASSERT(buffer != 0);
- RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
- chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
- chunkHead_->capacity = size - sizeof(ChunkHeader);
- chunkHead_->size = 0;
- chunkHead_->next = 0;
- }
-
- //! Destructor.
- /*! This deallocates all memory chunks, excluding the user-supplied buffer.
- */
- ~MemoryPoolAllocator() {
- Clear();
- RAPIDJSON_DELETE(ownBaseAllocator_);
- }
-
- //! Deallocates all memory chunks, excluding the user-supplied buffer.
- void Clear() {
- while (chunkHead_ && chunkHead_ != userBuffer_) {
- ChunkHeader* next = chunkHead_->next;
- baseAllocator_->Free(chunkHead_);
- chunkHead_ = next;
- }
- if (chunkHead_ && chunkHead_ == userBuffer_)
- chunkHead_->size = 0; // Clear user buffer
- }
-
- //! Computes the total capacity of allocated memory chunks.
- /*! \return total capacity in bytes.
- */
- size_t Capacity() const {
- size_t capacity = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
- capacity += c->capacity;
- return capacity;
- }
-
- //! Computes the memory blocks allocated.
- /*! \return total used bytes.
- */
- size_t Size() const {
- size_t size = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
- size += c->size;
- return size;
- }
-
- //! Allocates a memory block. (concept Allocator)
- void* Malloc(size_t size) {
- if (!size)
- return NULL;
-
- size = RAPIDJSON_ALIGN(size);
- if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
- if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
- return NULL;
-
- void *buffer = reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
- chunkHead_->size += size;
- return buffer;
- }
-
- //! Resizes a memory block (concept Allocator)
- void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
- if (originalPtr == 0)
- return Malloc(newSize);
-
- if (newSize == 0)
- return NULL;
-
- originalSize = RAPIDJSON_ALIGN(originalSize);
- newSize = RAPIDJSON_ALIGN(newSize);
-
- // Do not shrink if new size is smaller than original
- if (originalSize >= newSize)
- return originalPtr;
-
- // Simply expand it if it is the last allocation and there is sufficient space
- if (originalPtr == reinterpret_cast<char *>(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
- size_t increment = static_cast<size_t>(newSize - originalSize);
- if (chunkHead_->size + increment <= chunkHead_->capacity) {
- chunkHead_->size += increment;
- return originalPtr;
- }
- }
-
- // Realloc process: allocate and copy memory, do not free original buffer.
- if (void* newBuffer = Malloc(newSize)) {
- if (originalSize)
- std::memcpy(newBuffer, originalPtr, originalSize);
- return newBuffer;
- }
- else
- return NULL;
- }
-
- //! Frees a memory block (concept Allocator)
- static void Free(void *ptr) { (void)ptr; } // Do nothing
-
-private:
- //! Copy constructor is not permitted.
- MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
- //! Copy assignment operator is not permitted.
- MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
-
- //! Creates a new chunk.
- /*! \param capacity Capacity of the chunk in bytes.
- \return true if success.
- */
- bool AddChunk(size_t capacity) {
- if (!baseAllocator_)
- ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
- if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
- chunk->capacity = capacity;
- chunk->size = 0;
- chunk->next = chunkHead_;
- chunkHead_ = chunk;
- return true;
- }
- else
- return false;
- }
-
- static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
-
- //! Chunk header for perpending to each chunk.
- /*! Chunks are stored as a singly linked list.
- */
- struct ChunkHeader {
- size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
- size_t size; //!< Current size of allocated memory in bytes.
- ChunkHeader *next; //!< Next chunk in the linked list.
- };
-
- ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
- size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
- void *userBuffer_; //!< User supplied buffer.
- BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
- BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_ENCODINGS_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_DOCUMENT_H_
-#define RAPIDJSON_DOCUMENT_H_
-
-/*! \file document.h */
-
-#include "reader.h"
-#include "internal/meta.h"
-#include "internal/strfunc.h"
-#include "memorystream.h"
-#include "encodedstream.h"
-#include <new> // placement new
-#include <limits>
-
-RAPIDJSON_DIAG_PUSH
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_OFF(padded)
-RAPIDJSON_DIAG_OFF(switch-enum)
-RAPIDJSON_DIAG_OFF(c++98-compat)
-#endif
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_OFF(effc++)
-#if __GNUC__ >= 6
-RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions
-#endif
-#endif // __GNUC__
-
-#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
-#include <iterator> // std::iterator, std::random_access_iterator_tag
-#endif
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#include <utility> // std::move
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-// Forward declaration.
-template <typename Encoding, typename Allocator>
-class GenericValue;
-
-template <typename Encoding, typename Allocator, typename StackAllocator>
-class GenericDocument;
-
-//! Name-value pair in a JSON object value.
-/*!
- This class was internal to GenericValue. It used to be a inner struct.
- But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
- https://code.google.com/p/rapidjson/issues/detail?id=64
-*/
-template <typename Encoding, typename Allocator>
-struct GenericMember {
- GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
- GenericValue<Encoding, Allocator> value; //!< value of member.
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericMemberIterator
-
-#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
-
-//! (Constant) member iterator for a JSON object value
-/*!
- \tparam Const Is this a constant iterator?
- \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
- \tparam Allocator Allocator type for allocating memory of object, array and string.
-
- This class implements a Random Access Iterator for GenericMember elements
- of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
-
- \note This iterator implementation is mainly intended to avoid implicit
- conversions from iterator values to \c NULL,
- e.g. from GenericValue::FindMember.
-
- \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
- pointer-based implementation, if your platform doesn't provide
- the C++ <iterator> header.
-
- \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
- */
-template <bool Const, typename Encoding, typename Allocator>
-class GenericMemberIterator
- : public std::iterator<std::random_access_iterator_tag
- , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
-
- friend class GenericValue<Encoding,Allocator>;
- template <bool, typename, typename> friend class GenericMemberIterator;
-
- typedef GenericMember<Encoding,Allocator> PlainType;
- typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
- typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
-
-public:
- //! Iterator type itself
- typedef GenericMemberIterator Iterator;
- //! Constant iterator type
- typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
- //! Non-constant iterator type
- typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
-
- //! Pointer to (const) GenericMember
- typedef typename BaseType::pointer Pointer;
- //! Reference to (const) GenericMember
- typedef typename BaseType::reference Reference;
- //! Signed integer type (e.g. \c ptrdiff_t)
- typedef typename BaseType::difference_type DifferenceType;
-
- //! Default constructor (singular value)
- /*! Creates an iterator pointing to no element.
- \note All operations, except for comparisons, are undefined on such values.
- */
- GenericMemberIterator() : ptr_() {}
-
- //! Iterator conversions to more const
- /*!
- \param it (Non-const) iterator to copy from
-
- Allows the creation of an iterator from another GenericMemberIterator
- that is "less const". Especially, creating a non-constant iterator
- from a constant iterator are disabled:
- \li const -> non-const (not ok)
- \li const -> const (ok)
- \li non-const -> const (ok)
- \li non-const -> non-const (ok)
-
- \note If the \c Const template parameter is already \c false, this
- constructor effectively defines a regular copy-constructor.
- Otherwise, the copy constructor is implicitly defined.
- */
- GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
- Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; }
-
- //! @name stepping
- //@{
- Iterator& operator++(){ ++ptr_; return *this; }
- Iterator& operator--(){ --ptr_; return *this; }
- Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
- Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
- //@}
-
- //! @name increment/decrement
- //@{
- Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
- Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
-
- Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
- Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
- //@}
-
- //! @name relations
- //@{
- bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
- bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
- bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
- bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
- bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
- bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
- //@}
-
- //! @name dereference
- //@{
- Reference operator*() const { return *ptr_; }
- Pointer operator->() const { return ptr_; }
- Reference operator[](DifferenceType n) const { return ptr_[n]; }
- //@}
-
- //! Distance
- DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
-
-private:
- //! Internal constructor from plain pointer
- explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
-
- Pointer ptr_; //!< raw pointer
-};
-
-#else // RAPIDJSON_NOMEMBERITERATORCLASS
-
-// class-based member iterator implementation disabled, use plain pointers
-
-template <bool Const, typename Encoding, typename Allocator>
-struct GenericMemberIterator;
-
-//! non-const GenericMemberIterator
-template <typename Encoding, typename Allocator>
-struct GenericMemberIterator<false,Encoding,Allocator> {
- //! use plain pointer as iterator type
- typedef GenericMember<Encoding,Allocator>* Iterator;
-};
-//! const GenericMemberIterator
-template <typename Encoding, typename Allocator>
-struct GenericMemberIterator<true,Encoding,Allocator> {
- //! use plain const pointer as iterator type
- typedef const GenericMember<Encoding,Allocator>* Iterator;
-};
-
-#endif // RAPIDJSON_NOMEMBERITERATORCLASS
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericStringRef
-
-//! Reference to a constant string (not taking a copy)
-/*!
- \tparam CharType character type of the string
-
- This helper class is used to automatically infer constant string
- references for string literals, especially from \c const \b (!)
- character arrays.
-
- The main use is for creating JSON string values without copying the
- source string via an \ref Allocator. This requires that the referenced
- string pointers have a sufficient lifetime, which exceeds the lifetime
- of the associated GenericValue.
-
- \b Example
- \code
- Value v("foo"); // ok, no need to copy & calculate length
- const char foo[] = "foo";
- v.SetString(foo); // ok
-
- const char* bar = foo;
- // Value x(bar); // not ok, can't rely on bar's lifetime
- Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
- Value y(StringRef(bar, 3)); // ok, explicitly pass length
- \endcode
-
- \see StringRef, GenericValue::SetString
-*/
-template<typename CharType>
-struct GenericStringRef {
- typedef CharType Ch; //!< character type of the string
-
- //! Create string reference from \c const character array
-#ifndef __clang__ // -Wdocumentation
- /*!
- This constructor implicitly creates a constant string reference from
- a \c const character array. It has better performance than
- \ref StringRef(const CharType*) by inferring the string \ref length
- from the array length, and also supports strings containing null
- characters.
-
- \tparam N length of the string, automatically inferred
-
- \param str Constant character array, lifetime assumed to be longer
- than the use of the string in e.g. a GenericValue
-
- \post \ref s == str
-
- \note Constant complexity.
- \note There is a hidden, private overload to disallow references to
- non-const character arrays to be created via this constructor.
- By this, e.g. function-scope arrays used to be filled via
- \c snprintf are excluded from consideration.
- In such cases, the referenced string should be \b copied to the
- GenericValue instead.
- */
-#endif
- template<SizeType N>
- GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
- : s(str), length(N-1) {}
-
- //! Explicitly create string reference from \c const character pointer
-#ifndef __clang__ // -Wdocumentation
- /*!
- This constructor can be used to \b explicitly create a reference to
- a constant string pointer.
-
- \see StringRef(const CharType*)
-
- \param str Constant character pointer, lifetime assumed to be longer
- than the use of the string in e.g. a GenericValue
-
- \post \ref s == str
-
- \note There is a hidden, private overload to disallow references to
- non-const character arrays to be created via this constructor.
- By this, e.g. function-scope arrays used to be filled via
- \c snprintf are excluded from consideration.
- In such cases, the referenced string should be \b copied to the
- GenericValue instead.
- */
-#endif
- explicit GenericStringRef(const CharType* str)
- : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); }
-
- //! Create constant string reference from pointer and length
-#ifndef __clang__ // -Wdocumentation
- /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \param len length of the string, excluding the trailing NULL terminator
-
- \post \ref s == str && \ref length == len
- \note Constant complexity.
- */
-#endif
- GenericStringRef(const CharType* str, SizeType len)
- : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); }
-
- GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
-
- GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
-
- //! implicit conversion to plain CharType pointer
- operator const Ch *() const { return s; }
-
- const Ch* const s; //!< plain CharType pointer
- const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
-
-private:
- //! Disallow construction from non-const array
- template<SizeType N>
- GenericStringRef(CharType (&str)[N]) /* = delete */;
-};
-
-//! Mark a character pointer as constant string
-/*! Mark a plain character pointer as a "string literal". This function
- can be used to avoid copying a character string to be referenced as a
- value in a JSON GenericValue object, if the string's lifetime is known
- to be valid long enough.
- \tparam CharType Character type of the string
- \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \return GenericStringRef string reference object
- \relatesalso GenericStringRef
-
- \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
-*/
-template<typename CharType>
-inline GenericStringRef<CharType> StringRef(const CharType* str) {
- return GenericStringRef<CharType>(str, internal::StrLen(str));
-}
-
-//! Mark a character pointer as constant string
-/*! Mark a plain character pointer as a "string literal". This function
- can be used to avoid copying a character string to be referenced as a
- value in a JSON GenericValue object, if the string's lifetime is known
- to be valid long enough.
-
- This version has better performance with supplied length, and also
- supports string containing null characters.
-
- \tparam CharType character type of the string
- \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \param length The length of source string.
- \return GenericStringRef string reference object
- \relatesalso GenericStringRef
-*/
-template<typename CharType>
-inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
- return GenericStringRef<CharType>(str, SizeType(length));
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-//! Mark a string object as constant string
-/*! Mark a string object (e.g. \c std::string) as a "string literal".
- This function can be used to avoid copying a string to be referenced as a
- value in a JSON GenericValue object, if the string's lifetime is known
- to be valid long enough.
-
- \tparam CharType character type of the string
- \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \return GenericStringRef string reference object
- \relatesalso GenericStringRef
- \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
-*/
-template<typename CharType>
-inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
- return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericValue type traits
-namespace internal {
-
-template <typename T, typename Encoding = void, typename Allocator = void>
-struct IsGenericValueImpl : FalseType {};
-
-// select candidates according to nested encoding and allocator types
-template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
- : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
-
-// helper to match arbitrary GenericValue instantiations, including derived classes
-template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
-
-} // namespace internal
-
-///////////////////////////////////////////////////////////////////////////////
-// TypeHelper
-
-namespace internal {
-
-template <typename ValueType, typename T>
-struct TypeHelper {};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, bool> {
- static bool Is(const ValueType& v) { return v.IsBool(); }
- static bool Get(const ValueType& v) { return v.GetBool(); }
- static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
- static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, int> {
- static bool Is(const ValueType& v) { return v.IsInt(); }
- static int Get(const ValueType& v) { return v.GetInt(); }
- static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
- static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, unsigned> {
- static bool Is(const ValueType& v) { return v.IsUint(); }
- static unsigned Get(const ValueType& v) { return v.GetUint(); }
- static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); }
- static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, int64_t> {
- static bool Is(const ValueType& v) { return v.IsInt64(); }
- static int64_t Get(const ValueType& v) { return v.GetInt64(); }
- static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); }
- static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, uint64_t> {
- static bool Is(const ValueType& v) { return v.IsUint64(); }
- static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
- static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); }
- static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, double> {
- static bool Is(const ValueType& v) { return v.IsDouble(); }
- static double Get(const ValueType& v) { return v.GetDouble(); }
- static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); }
- static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, float> {
- static bool Is(const ValueType& v) { return v.IsFloat(); }
- static float Get(const ValueType& v) { return v.GetFloat(); }
- static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
- static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, const typename ValueType::Ch*> {
- typedef const typename ValueType::Ch* StringType;
- static bool Is(const ValueType& v) { return v.IsString(); }
- static StringType Get(const ValueType& v) { return v.GetString(); }
- static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); }
- static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
-};
-
-#if RAPIDJSON_HAS_STDSTRING
-template<typename ValueType>
-struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
- typedef std::basic_string<typename ValueType::Ch> StringType;
- static bool Is(const ValueType& v) { return v.IsString(); }
- static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); }
- static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); }
-};
-#endif
-
-template<typename ValueType>
-struct TypeHelper<ValueType, typename ValueType::Array> {
- typedef typename ValueType::Array ArrayType;
- static bool Is(const ValueType& v) { return v.IsArray(); }
- static ArrayType Get(ValueType& v) { return v.GetArray(); }
- static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
- static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, typename ValueType::ConstArray> {
- typedef typename ValueType::ConstArray ArrayType;
- static bool Is(const ValueType& v) { return v.IsArray(); }
- static ArrayType Get(const ValueType& v) { return v.GetArray(); }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, typename ValueType::Object> {
- typedef typename ValueType::Object ObjectType;
- static bool Is(const ValueType& v) { return v.IsObject(); }
- static ObjectType Get(ValueType& v) { return v.GetObject(); }
- static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
- static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; }
-};
-
-template<typename ValueType>
-struct TypeHelper<ValueType, typename ValueType::ConstObject> {
- typedef typename ValueType::ConstObject ObjectType;
- static bool Is(const ValueType& v) { return v.IsObject(); }
- static ObjectType Get(const ValueType& v) { return v.GetObject(); }
-};
-
-} // namespace internal
-
-// Forward declarations
-template <bool, typename> class GenericArray;
-template <bool, typename> class GenericObject;
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericValue
-
-//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
-/*!
- A JSON value can be one of 7 types. This class is a variant type supporting
- these types.
-
- Use the Value if UTF8 and default allocator
-
- \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
- \tparam Allocator Allocator type for allocating memory of object, array and string.
-*/
-template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
-class GenericValue {
-public:
- //! Name-value pair in an object.
- typedef GenericMember<Encoding, Allocator> Member;
- typedef Encoding EncodingType; //!< Encoding type from template parameter.
- typedef Allocator AllocatorType; //!< Allocator type from template parameter.
- typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
- typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
- typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
- typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
- typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
- typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
- typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of itself.
- typedef GenericArray<false, ValueType> Array;
- typedef GenericArray<true, ValueType> ConstArray;
- typedef GenericObject<false, ValueType> Object;
- typedef GenericObject<true, ValueType> ConstObject;
-
- //!@name Constructors and destructor.
- //@{
-
- //! Default constructor creates a null value.
- GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move constructor in C++11
- GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
- rhs.data_.f.flags = kNullFlag; // give up contents
- }
-#endif
-
-private:
- //! Copy constructor is not permitted.
- GenericValue(const GenericValue& rhs);
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Moving from a GenericDocument is not permitted.
- template <typename StackAllocator>
- GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
-
- //! Move assignment from a GenericDocument is not permitted.
- template <typename StackAllocator>
- GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
-#endif
-
-public:
-
- //! Constructor with JSON value type.
- /*! This creates a Value of specified type with default content.
- \param type Type of the value.
- \note Default content for number is zero.
- */
- explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
- static const uint16_t defaultFlags[7] = {
- kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
- kNumberAnyFlag
- };
- RAPIDJSON_ASSERT(type <= kNumberType);
- data_.f.flags = defaultFlags[type];
-
- // Use ShortString to store empty string.
- if (type == kStringType)
- data_.ss.SetLength(0);
- }
-
- //! Explicit copy constructor (with allocator)
- /*! Creates a copy of a Value by using the given Allocator
- \tparam SourceAllocator allocator of \c rhs
- \param rhs Value to copy from (read-only)
- \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
- \see CopyFrom()
- */
- template< typename SourceAllocator >
- GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
-
- //! Constructor for boolean value.
- /*! \param b Boolean value
- \note This constructor is limited to \em real boolean values and rejects
- implicitly converted types like arbitrary pointers. Use an explicit cast
- to \c bool, if you want to construct a boolean JSON value in such cases.
- */
-#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
- template <typename T>
- explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
-#else
- explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
-#endif
- : data_() {
- // safe-guard against failing SFINAE
- RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
- data_.f.flags = b ? kTrueFlag : kFalseFlag;
- }
-
- //! Constructor for int value.
- explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
- data_.n.i64 = i;
- data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag;
- }
-
- //! Constructor for unsigned value.
- explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
- data_.n.u64 = u;
- data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
- }
-
- //! Constructor for int64_t value.
- explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
- data_.n.i64 = i64;
- data_.f.flags = kNumberInt64Flag;
- if (i64 >= 0) {
- data_.f.flags |= kNumberUint64Flag;
- if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
- data_.f.flags |= kUintFlag;
- if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- data_.f.flags |= kIntFlag;
- }
- else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- data_.f.flags |= kIntFlag;
- }
-
- //! Constructor for uint64_t value.
- explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
- data_.n.u64 = u64;
- data_.f.flags = kNumberUint64Flag;
- if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
- data_.f.flags |= kInt64Flag;
- if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
- data_.f.flags |= kUintFlag;
- if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- data_.f.flags |= kIntFlag;
- }
-
- //! Constructor for double value.
- explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
-
- //! Constructor for constant string (i.e. do not make a copy of string)
- GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
-
- //! Constructor for constant string (i.e. do not make a copy of string)
- explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); }
-
- //! Constructor for copy-string (i.e. do make a copy of string)
- GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
-
- //! Constructor for copy-string (i.e. do make a copy of string)
- GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Constructor for copy-string from a string object (i.e. do make a copy of string)
- /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
-#endif
-
- //! Constructor for Array.
- /*!
- \param a An array obtained by \c GetArray().
- \note \c Array is always pass-by-value.
- \note the source array is moved into this value and the sourec array becomes empty.
- */
- GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
- a.value_.data_ = Data();
- a.value_.data_.f.flags = kArrayFlag;
- }
-
- //! Constructor for Object.
- /*!
- \param o An object obtained by \c GetObject().
- \note \c Object is always pass-by-value.
- \note the source object is moved into this value and the sourec object becomes empty.
- */
- GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
- o.value_.data_ = Data();
- o.value_.data_.f.flags = kObjectFlag;
- }
-
- //! Destructor.
- /*! Need to destruct elements of array, members of object, or copy-string.
- */
- ~GenericValue() {
- if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
- switch(data_.f.flags) {
- case kArrayFlag:
- {
- GenericValue* e = GetElementsPointer();
- for (GenericValue* v = e; v != e + data_.a.size; ++v)
- v->~GenericValue();
- Allocator::Free(e);
- }
- break;
-
- case kObjectFlag:
- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
- m->~Member();
- Allocator::Free(GetMembersPointer());
- break;
-
- case kCopyStringFlag:
- Allocator::Free(const_cast<Ch*>(GetStringPointer()));
- break;
-
- default:
- break; // Do nothing for other types.
- }
- }
- }
-
- //@}
-
- //!@name Assignment operators
- //@{
-
- //! Assignment with move semantics.
- /*! \param rhs Source of the assignment. It will become a null value after assignment.
- */
- GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
- RAPIDJSON_ASSERT(this != &rhs);
- this->~GenericValue();
- RawAssign(rhs);
- return *this;
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move assignment in C++11
- GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
- return *this = rhs.Move();
- }
-#endif
-
- //! Assignment of constant string reference (no copy)
- /*! \param str Constant string reference to be assigned
- \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
- \see GenericStringRef, operator=(T)
- */
- GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
- GenericValue s(str);
- return *this = s;
- }
-
- //! Assignment with primitive types.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param value The value to be assigned.
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref SetString(const Ch*, Allocator&) (for copying) or
- \ref StringRef() (to explicitly mark the pointer as constant) instead.
- All other pointer types would implicitly convert to \c bool,
- use \ref SetBool() instead.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
- operator=(T value) {
- GenericValue v(value);
- return *this = v;
- }
-
- //! Deep-copy assignment from Value
- /*! Assigns a \b copy of the Value to the current Value object
- \tparam SourceAllocator Allocator type of \c rhs
- \param rhs Value to copy from (read-only)
- \param allocator Allocator to use for copying
- */
- template <typename SourceAllocator>
- GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
- RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
- this->~GenericValue();
- new (this) GenericValue(rhs, allocator);
- return *this;
- }
-
- //! Exchange the contents of this value with those of other.
- /*!
- \param other Another value.
- \note Constant complexity.
- */
- GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
- GenericValue temp;
- temp.RawAssign(*this);
- RawAssign(other);
- other.RawAssign(temp);
- return *this;
- }
-
- //! free-standing swap function helper
- /*!
- Helper function to enable support for common swap implementation pattern based on \c std::swap:
- \code
- void swap(MyClass& a, MyClass& b) {
- using std::swap;
- swap(a.value, b.value);
- // ...
- }
- \endcode
- \see Swap()
- */
- friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
-
- //! Prepare Value for move semantics
- /*! \return *this */
- GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
- //@}
-
- //!@name Equal-to and not-equal-to operators
- //@{
- //! Equal-to operator
- /*!
- \note If an object contains duplicated named member, comparing equality with any object is always \c false.
- \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
- */
- template <typename SourceAllocator>
- bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
- typedef GenericValue<Encoding, SourceAllocator> RhsType;
- if (GetType() != rhs.GetType())
- return false;
-
- switch (GetType()) {
- case kObjectType: // Warning: O(n^2) inner-loop
- if (data_.o.size != rhs.data_.o.size)
- return false;
- for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
- typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
- if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
- return false;
- }
- return true;
-
- case kArrayType:
- if (data_.a.size != rhs.data_.a.size)
- return false;
- for (SizeType i = 0; i < data_.a.size; i++)
- if ((*this)[i] != rhs[i])
- return false;
- return true;
-
- case kStringType:
- return StringEqual(rhs);
-
- case kNumberType:
- if (IsDouble() || rhs.IsDouble()) {
- double a = GetDouble(); // May convert from integer to double.
- double b = rhs.GetDouble(); // Ditto
- return a >= b && a <= b; // Prevent -Wfloat-equal
- }
- else
- return data_.n.u64 == rhs.data_.n.u64;
-
- default:
- return true;
- }
- }
-
- //! Equal-to operator with const C-string pointer
- bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Equal-to operator with string object
- /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
-#endif
-
- //! Equal-to operator with primitive types
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
- */
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
-
- //! Not-equal-to operator
- /*! \return !(*this == rhs)
- */
- template <typename SourceAllocator>
- bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
-
- //! Not-equal-to operator with const C-string pointer
- bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
-
- //! Not-equal-to operator with arbitrary types
- /*! \return !(*this == rhs)
- */
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
-
- //! Equal-to operator with arbitrary types (symmetric version)
- /*! \return (rhs == lhs)
- */
- template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
-
- //! Not-Equal-to operator with arbitrary types (symmetric version)
- /*! \return !(rhs == lhs)
- */
- template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
- //@}
-
- //!@name Type
- //@{
-
- Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask); }
- bool IsNull() const { return data_.f.flags == kNullFlag; }
- bool IsFalse() const { return data_.f.flags == kFalseFlag; }
- bool IsTrue() const { return data_.f.flags == kTrueFlag; }
- bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
- bool IsObject() const { return data_.f.flags == kObjectFlag; }
- bool IsArray() const { return data_.f.flags == kArrayFlag; }
- bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
- bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
- bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
- bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
- bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
- bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
- bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
-
- // Checks whether a number can be losslessly converted to a double.
- bool IsLosslessDouble() const {
- if (!IsNumber()) return false;
- if (IsUint64()) {
- uint64_t u = GetUint64();
- volatile double d = static_cast<double>(u);
- return (d >= 0.0)
- && (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
- && (u == static_cast<uint64_t>(d));
- }
- if (IsInt64()) {
- int64_t i = GetInt64();
- volatile double d = static_cast<double>(i);
- return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
- && (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
- && (i == static_cast<int64_t>(d));
- }
- return true; // double, int, uint are always lossless
- }
-
- // Checks whether a number is a float (possible lossy).
- bool IsFloat() const {
- if ((data_.f.flags & kDoubleFlag) == 0)
- return false;
- double d = GetDouble();
- return d >= -3.4028234e38 && d <= 3.4028234e38;
- }
- // Checks whether a number can be losslessly converted to a float.
- bool IsLosslessFloat() const {
- if (!IsNumber()) return false;
- double a = GetDouble();
- if (a < static_cast<double>(-std::numeric_limits<float>::max())
- || a > static_cast<double>(std::numeric_limits<float>::max()))
- return false;
- double b = static_cast<double>(static_cast<float>(a));
- return a >= b && a <= b; // Prevent -Wfloat-equal
- }
-
- //@}
-
- //!@name Null
- //@{
-
- GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
-
- //@}
-
- //!@name Bool
- //@{
-
- bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; }
- //!< Set boolean value
- /*! \post IsBool() == true */
- GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
-
- //@}
-
- //!@name Object
- //@{
-
- //! Set this value as an empty object.
- /*! \post IsObject() == true */
- GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
-
- //! Get the number of members in the object.
- SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
-
- //! Check whether the object is empty.
- bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
-
- //! Get a value from an object associated with the name.
- /*! \pre IsObject() == true
- \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
- \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
- Since 0.2, if the name is not correct, it will assert.
- If user is unsure whether a member exists, user should use HasMember() first.
- A better approach is to use FindMember().
- \note Linear time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
- GenericValue n(StringRef(name));
- return (*this)[n];
- }
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
-
- //! Get a value from an object associated with the name.
- /*! \pre IsObject() == true
- \tparam SourceAllocator Allocator of the \c name value
-
- \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
- And it can also handle strings with embedded null characters.
-
- \note Linear time complexity.
- */
- template <typename SourceAllocator>
- GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
- MemberIterator member = FindMember(name);
- if (member != MemberEnd())
- return member->value;
- else {
- RAPIDJSON_ASSERT(false); // see above note
-
- // This will generate -Wexit-time-destructors in clang
- // static GenericValue NullValue;
- // return NullValue;
-
- // Use static buffer and placement-new to prevent destruction
- static char buffer[sizeof(GenericValue)];
- return *new (buffer) GenericValue();
- }
- }
- template <typename SourceAllocator>
- const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Get a value from an object associated with name (string object).
- GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this)[GenericValue(StringRef(name))]; }
- const GenericValue& operator[](const std::basic_string<Ch>& name) const { return (*this)[GenericValue(StringRef(name))]; }
-#endif
-
- //! Const member iterator
- /*! \pre IsObject() == true */
- ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); }
- //! Const \em past-the-end member iterator
- /*! \pre IsObject() == true */
- ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); }
- //! Member iterator
- /*! \pre IsObject() == true */
- MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); }
- //! \em Past-the-end member iterator
- /*! \pre IsObject() == true */
- MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
-
- //! Check whether a member exists in the object.
- /*!
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Whether a member with that name exists.
- \note It is better to use FindMember() directly if you need the obtain the value as well.
- \note Linear time complexity.
- */
- bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Check whether a member exists in the object with string object.
- /*!
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Whether a member with that name exists.
- \note It is better to use FindMember() directly if you need the obtain the value as well.
- \note Linear time complexity.
- */
- bool HasMember(const std::basic_string<Ch>& name) const { return FindMember(name) != MemberEnd(); }
-#endif
-
- //! Check whether a member exists in the object with GenericValue name.
- /*!
- This version is faster because it does not need a StrLen(). It can also handle string with null character.
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Whether a member with that name exists.
- \note It is better to use FindMember() directly if you need the obtain the value as well.
- \note Linear time complexity.
- */
- template <typename SourceAllocator>
- bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
-
- //! Find member by name.
- /*!
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Iterator to member, if it exists.
- Otherwise returns \ref MemberEnd().
-
- \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
- the requested member doesn't exist. For consistency with e.g.
- \c std::map, this has been changed to MemberEnd() now.
- \note Linear time complexity.
- */
- MemberIterator FindMember(const Ch* name) {
- GenericValue n(StringRef(name));
- return FindMember(n);
- }
-
- ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
-
- //! Find member by name.
- /*!
- This version is faster because it does not need a StrLen(). It can also handle string with null character.
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Iterator to member, if it exists.
- Otherwise returns \ref MemberEnd().
-
- \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
- the requested member doesn't exist. For consistency with e.g.
- \c std::map, this has been changed to MemberEnd() now.
- \note Linear time complexity.
- */
- template <typename SourceAllocator>
- MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(name.IsString());
- MemberIterator member = MemberBegin();
- for ( ; member != MemberEnd(); ++member)
- if (name.StringEqual(member->name))
- break;
- return member;
- }
- template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Find member by string object name.
- /*!
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Iterator to member, if it exists.
- Otherwise returns \ref MemberEnd().
- */
- MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMember(GenericValue(StringRef(name))); }
- ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { return FindMember(GenericValue(StringRef(name))); }
-#endif
-
- //! Add a member (name-value pair) to the object.
- /*! \param name A string value as name of member.
- \param value Value of any type.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \note The ownership of \c name and \c value will be transferred to this object on success.
- \pre IsObject() && name.IsString()
- \post name.IsNull() && value.IsNull()
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(name.IsString());
-
- ObjectData& o = data_.o;
- if (o.size >= o.capacity) {
- if (o.capacity == 0) {
- o.capacity = kDefaultObjectCapacity;
- SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))));
- }
- else {
- SizeType oldCapacity = o.capacity;
- o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
- SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
- }
- }
- Member* members = GetMembersPointer();
- members[o.size].name.RawAssign(name);
- members[o.size].value.RawAssign(value);
- o.size++;
- return *this;
- }
-
- //! Add a constant string value as member (name-value pair) to the object.
- /*! \param name A string value as name of member.
- \param value constant string reference as value of member.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
- \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
- GenericValue v(value);
- return AddMember(name, v, allocator);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Add a string object as member (name-value pair) to the object.
- /*! \param name A string value as name of member.
- \param value constant string reference as value of member.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
- \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(GenericValue& name, std::basic_string<Ch>& value, Allocator& allocator) {
- GenericValue v(value, allocator);
- return AddMember(name, v, allocator);
- }
-#endif
-
- //! Add any primitive value as member (name-value pair) to the object.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param name A string value as name of member.
- \param value Value of primitive type \c T as value of member
- \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
- AddMember(StringRefType, StringRefType, Allocator&).
- All other pointer types would implicitly convert to \c bool,
- use an explicit cast instead, if needed.
- \note Amortized Constant time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
- AddMember(GenericValue& name, T value, Allocator& allocator) {
- GenericValue v(value);
- return AddMember(name, v, allocator);
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
- return AddMember(name, value, allocator);
- }
- GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
- return AddMember(name, value, allocator);
- }
- GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
- return AddMember(name, value, allocator);
- }
- GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
- GenericValue n(name);
- return AddMember(n, value, allocator);
- }
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
-
-
- //! Add a member (name-value pair) to the object.
- /*! \param name A constant string reference as name of member.
- \param value Value of any type.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \note The ownership of \c value will be transferred to this object on success.
- \pre IsObject()
- \post value.IsNull()
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
- GenericValue n(name);
- return AddMember(n, value, allocator);
- }
-
- //! Add a constant string value as member (name-value pair) to the object.
- /*! \param name A constant string reference as name of member.
- \param value constant string reference as value of member.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
- \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
- GenericValue v(value);
- return AddMember(name, v, allocator);
- }
-
- //! Add any primitive value as member (name-value pair) to the object.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param name A constant string reference as name of member.
- \param value Value of primitive type \c T as value of member
- \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
- AddMember(StringRefType, StringRefType, Allocator&).
- All other pointer types would implicitly convert to \c bool,
- use an explicit cast instead, if needed.
- \note Amortized Constant time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
- AddMember(StringRefType name, T value, Allocator& allocator) {
- GenericValue n(name);
- return AddMember(n, value, allocator);
- }
-
- //! Remove all members in the object.
- /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
- \note Linear time complexity.
- */
- void RemoveAllMembers() {
- RAPIDJSON_ASSERT(IsObject());
- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
- m->~Member();
- data_.o.size = 0;
- }
-
- //! Remove a member in object by its name.
- /*! \param name Name of member to be removed.
- \return Whether the member existed.
- \note This function may reorder the object members. Use \ref
- EraseMember(ConstMemberIterator) if you need to preserve the
- relative order of the remaining members.
- \note Linear time complexity.
- */
- bool RemoveMember(const Ch* name) {
- GenericValue n(StringRef(name));
- return RemoveMember(n);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool RemoveMember(const std::basic_string<Ch>& name) { return RemoveMember(GenericValue(StringRef(name))); }
-#endif
-
- template <typename SourceAllocator>
- bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
- MemberIterator m = FindMember(name);
- if (m != MemberEnd()) {
- RemoveMember(m);
- return true;
- }
- else
- return false;
- }
-
- //! Remove a member in object by iterator.
- /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
- \return the new iterator after removal.
- \note This function may reorder the object members. Use \ref
- EraseMember(ConstMemberIterator) if you need to preserve the
- relative order of the remaining members.
- \note Constant time complexity.
- */
- MemberIterator RemoveMember(MemberIterator m) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(data_.o.size > 0);
- RAPIDJSON_ASSERT(GetMembersPointer() != 0);
- RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
-
- MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
- if (data_.o.size > 1 && m != last)
- *m = *last; // Move the last one to this place
- else
- m->~Member(); // Only one left, just destroy
- --data_.o.size;
- return m;
- }
-
- //! Remove a member from an object by iterator.
- /*! \param pos iterator to the member to remove
- \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
- \return Iterator following the removed element.
- If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
- \note This function preserves the relative order of the remaining object
- members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
- \note Linear time complexity.
- */
- MemberIterator EraseMember(ConstMemberIterator pos) {
- return EraseMember(pos, pos +1);
- }
-
- //! Remove members in the range [first, last) from an object.
- /*! \param first iterator to the first member to remove
- \param last iterator following the last member to remove
- \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
- \return Iterator following the last removed element.
- \note This function preserves the relative order of the remaining object
- members.
- \note Linear time complexity.
- */
- MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(data_.o.size > 0);
- RAPIDJSON_ASSERT(GetMembersPointer() != 0);
- RAPIDJSON_ASSERT(first >= MemberBegin());
- RAPIDJSON_ASSERT(first <= last);
- RAPIDJSON_ASSERT(last <= MemberEnd());
-
- MemberIterator pos = MemberBegin() + (first - MemberBegin());
- for (MemberIterator itr = pos; itr != last; ++itr)
- itr->~Member();
- std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
- data_.o.size -= static_cast<SizeType>(last - first);
- return pos;
- }
-
- //! Erase a member in object by its name.
- /*! \param name Name of member to be removed.
- \return Whether the member existed.
- \note Linear time complexity.
- */
- bool EraseMember(const Ch* name) {
- GenericValue n(StringRef(name));
- return EraseMember(n);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(GenericValue(StringRef(name))); }
-#endif
-
- template <typename SourceAllocator>
- bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
- MemberIterator m = FindMember(name);
- if (m != MemberEnd()) {
- EraseMember(m);
- return true;
- }
- else
- return false;
- }
-
- Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
- ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); }
-
- //@}
-
- //!@name Array
- //@{
-
- //! Set this value as an empty array.
- /*! \post IsArray == true */
- GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
-
- //! Get the number of elements in array.
- SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
-
- //! Get the capacity of array.
- SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
-
- //! Check whether the array is empty.
- bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
-
- //! Remove all elements in the array.
- /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
- \note Linear time complexity.
- */
- void Clear() {
- RAPIDJSON_ASSERT(IsArray());
- GenericValue* e = GetElementsPointer();
- for (GenericValue* v = e; v != e + data_.a.size; ++v)
- v->~GenericValue();
- data_.a.size = 0;
- }
-
- //! Get an element from array by index.
- /*! \pre IsArray() == true
- \param index Zero-based index of element.
- \see operator[](T*)
- */
- GenericValue& operator[](SizeType index) {
- RAPIDJSON_ASSERT(IsArray());
- RAPIDJSON_ASSERT(index < data_.a.size);
- return GetElementsPointer()[index];
- }
- const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
-
- //! Element iterator
- /*! \pre IsArray() == true */
- ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); }
- //! \em Past-the-end element iterator
- /*! \pre IsArray() == true */
- ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; }
- //! Constant element iterator
- /*! \pre IsArray() == true */
- ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
- //! Constant \em past-the-end element iterator
- /*! \pre IsArray() == true */
- ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
-
- //! Request the array to have enough capacity to store elements.
- /*! \param newCapacity The capacity that the array at least need to have.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \note Linear time complexity.
- */
- GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
- RAPIDJSON_ASSERT(IsArray());
- if (newCapacity > data_.a.capacity) {
- SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue))));
- data_.a.capacity = newCapacity;
- }
- return *this;
- }
-
- //! Append a GenericValue at the end of the array.
- /*! \param value Value to be appended.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \pre IsArray() == true
- \post value.IsNull() == true
- \return The value itself for fluent API.
- \note The ownership of \c value will be transferred to this array on success.
- \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
- \note Amortized constant time complexity.
- */
- GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
- RAPIDJSON_ASSERT(IsArray());
- if (data_.a.size >= data_.a.capacity)
- Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
- GetElementsPointer()[data_.a.size++].RawAssign(value);
- return *this;
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
- return PushBack(value, allocator);
- }
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
-
- //! Append a constant string reference at the end of the array.
- /*! \param value Constant string reference to be appended.
- \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
- \pre IsArray() == true
- \return The value itself for fluent API.
- \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
- \note Amortized constant time complexity.
- \see GenericStringRef
- */
- GenericValue& PushBack(StringRefType value, Allocator& allocator) {
- return (*this).template PushBack<StringRefType>(value, allocator);
- }
-
- //! Append a primitive value at the end of the array.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param value Value of primitive type T to be appended.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \pre IsArray() == true
- \return The value itself for fluent API.
- \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref PushBack(GenericValue&, Allocator&) or \ref
- PushBack(StringRefType, Allocator&).
- All other pointer types would implicitly convert to \c bool,
- use an explicit cast instead, if needed.
- \note Amortized constant time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
- PushBack(T value, Allocator& allocator) {
- GenericValue v(value);
- return PushBack(v, allocator);
- }
-
- //! Remove the last element in the array.
- /*!
- \note Constant time complexity.
- */
- GenericValue& PopBack() {
- RAPIDJSON_ASSERT(IsArray());
- RAPIDJSON_ASSERT(!Empty());
- GetElementsPointer()[--data_.a.size].~GenericValue();
- return *this;
- }
-
- //! Remove an element of array by iterator.
- /*!
- \param pos iterator to the element to remove
- \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
- \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
- \note Linear time complexity.
- */
- ValueIterator Erase(ConstValueIterator pos) {
- return Erase(pos, pos + 1);
- }
-
- //! Remove elements in the range [first, last) of the array.
- /*!
- \param first iterator to the first element to remove
- \param last iterator following the last element to remove
- \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
- \return Iterator following the last removed element.
- \note Linear time complexity.
- */
- ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
- RAPIDJSON_ASSERT(IsArray());
- RAPIDJSON_ASSERT(data_.a.size > 0);
- RAPIDJSON_ASSERT(GetElementsPointer() != 0);
- RAPIDJSON_ASSERT(first >= Begin());
- RAPIDJSON_ASSERT(first <= last);
- RAPIDJSON_ASSERT(last <= End());
- ValueIterator pos = Begin() + (first - Begin());
- for (ValueIterator itr = pos; itr != last; ++itr)
- itr->~GenericValue();
- std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
- data_.a.size -= static_cast<SizeType>(last - first);
- return pos;
- }
-
- Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
- ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); }
-
- //@}
-
- //!@name Number
- //@{
-
- int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; }
- unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; }
- int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; }
- uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; }
-
- //! Get the value as double type.
- /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless.
- */
- double GetDouble() const {
- RAPIDJSON_ASSERT(IsNumber());
- if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
- if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double
- if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
- if ((data_.f.flags & kInt64Flag) != 0) return static_cast<double>(data_.n.i64); // int64_t -> double (may lose precision)
- RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast<double>(data_.n.u64); // uint64_t -> double (may lose precision)
- }
-
- //! Get the value as float type.
- /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless.
- */
- float GetFloat() const {
- return static_cast<float>(GetDouble());
- }
-
- GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
- GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
- GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
- GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
- GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
- GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
-
- //@}
-
- //!@name String
- //@{
-
- const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
-
- //! Get the length of string.
- /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
- */
- SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
-
- //! Set this value as a string without copying source string.
- /*! This version has better performance with supplied length, and also support string containing null character.
- \param s source string pointer.
- \param length The length of source string, excluding the trailing null terminator.
- \return The value itself for fluent API.
- \post IsString() == true && GetString() == s && GetStringLength() == length
- \see SetString(StringRefType)
- */
- GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
-
- //! Set this value as a string without copying source string.
- /*! \param s source string reference
- \return The value itself for fluent API.
- \post IsString() == true && GetString() == s && GetStringLength() == s.length
- */
- GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
-
- //! Set this value as a string by copying from source string.
- /*! This version has better performance with supplied length, and also support string containing null character.
- \param s source string.
- \param length The length of source string, excluding the trailing null terminator.
- \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
- */
- GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
-
- //! Set this value as a string by copying from source string.
- /*! \param s source string.
- \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
- */
- GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Set this value as a string by copying from source string.
- /*! \param s source string.
- \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
- \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
-#endif
-
- //@}
-
- //!@name Array
- //@{
-
- //! Templated version for checking whether this value is type T.
- /*!
- \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string<Ch>
- */
- template <typename T>
- bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
-
- template <typename T>
- T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
-
- template <typename T>
- T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
-
- template<typename T>
- ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::Set(*this, data); }
-
- template<typename T>
- ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper<ValueType, T>::Set(*this, data, allocator); }
-
- //@}
-
- //! Generate events of this value to a Handler.
- /*! This function adopts the GoF visitor pattern.
- Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
- It can also be used to deep clone this value via GenericDocument, which is also a Handler.
- \tparam Handler type of handler.
- \param handler An object implementing concept Handler.
- */
- template <typename Handler>
- bool Accept(Handler& handler) const {
- switch(GetType()) {
- case kNullType: return handler.Null();
- case kFalseType: return handler.Bool(false);
- case kTrueType: return handler.Bool(true);
-
- case kObjectType:
- if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
- return false;
- for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
- RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
- if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
- return false;
- if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
- return false;
- }
- return handler.EndObject(data_.o.size);
-
- case kArrayType:
- if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
- return false;
- for (const GenericValue* v = Begin(); v != End(); ++v)
- if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
- return false;
- return handler.EndArray(data_.a.size);
-
- case kStringType:
- return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
-
- default:
- RAPIDJSON_ASSERT(GetType() == kNumberType);
- if (IsDouble()) return handler.Double(data_.n.d);
- else if (IsInt()) return handler.Int(data_.n.i.i);
- else if (IsUint()) return handler.Uint(data_.n.u.u);
- else if (IsInt64()) return handler.Int64(data_.n.i64);
- else return handler.Uint64(data_.n.u64);
- }
- }
-
-private:
- template <typename, typename> friend class GenericValue;
- template <typename, typename, typename> friend class GenericDocument;
-
- enum {
- kBoolFlag = 0x0008,
- kNumberFlag = 0x0010,
- kIntFlag = 0x0020,
- kUintFlag = 0x0040,
- kInt64Flag = 0x0080,
- kUint64Flag = 0x0100,
- kDoubleFlag = 0x0200,
- kStringFlag = 0x0400,
- kCopyFlag = 0x0800,
- kInlineStrFlag = 0x1000,
-
- // Initial flags of different types.
- kNullFlag = kNullType,
- kTrueFlag = kTrueType | kBoolFlag,
- kFalseFlag = kFalseType | kBoolFlag,
- kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
- kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
- kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
- kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
- kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
- kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
- kConstStringFlag = kStringType | kStringFlag,
- kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
- kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
- kObjectFlag = kObjectType,
- kArrayFlag = kArrayType,
-
- kTypeMask = 0x07
- };
-
- static const SizeType kDefaultArrayCapacity = 16;
- static const SizeType kDefaultObjectCapacity = 16;
-
- struct Flag {
-#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
- char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer
-#elif RAPIDJSON_64BIT
- char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes
-#else
- char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes
-#endif
- uint16_t flags;
- };
-
- struct String {
- SizeType length;
- SizeType hashcode; //!< reserved
- const Ch* str;
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
- // (excluding the terminating zero) and store a value to determine the length of the contained
- // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
- // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
- // the string terminator as well. For getting the string length back from that value just use
- // "MaxSize - str[LenPos]".
- // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode,
- // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings).
- struct ShortString {
- enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
- Ch str[MaxChars];
-
- inline static bool Usable(SizeType len) { return (MaxSize >= len); }
- inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(MaxSize - len); }
- inline SizeType GetLength() const { return static_cast<SizeType>(MaxSize - str[LenPos]); }
- }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- // By using proper binary layout, retrieval of different integer types do not need conversions.
- union Number {
-#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
- struct I {
- int i;
- char padding[4];
- }i;
- struct U {
- unsigned u;
- char padding2[4];
- }u;
-#else
- struct I {
- char padding[4];
- int i;
- }i;
- struct U {
- char padding2[4];
- unsigned u;
- }u;
-#endif
- int64_t i64;
- uint64_t u64;
- double d;
- }; // 8 bytes
-
- struct ObjectData {
- SizeType size;
- SizeType capacity;
- Member* members;
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- struct ArrayData {
- SizeType size;
- SizeType capacity;
- GenericValue* elements;
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- union Data {
- String s;
- ShortString ss;
- Number n;
- ObjectData o;
- ArrayData a;
- Flag f;
- }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION
-
- RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); }
- RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); }
- RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); }
- RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
- RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); }
- RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); }
-
- // Initialize this value as array with initial data, without calling destructor.
- void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
- data_.f.flags = kArrayFlag;
- if (count) {
- GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
- SetElementsPointer(e);
- std::memcpy(e, values, count * sizeof(GenericValue));
- }
- else
- SetElementsPointer(0);
- data_.a.size = data_.a.capacity = count;
- }
-
- //! Initialize this value as object with initial data, without calling destructor.
- void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
- data_.f.flags = kObjectFlag;
- if (count) {
- Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
- SetMembersPointer(m);
- std::memcpy(m, members, count * sizeof(Member));
- }
- else
- SetMembersPointer(0);
- data_.o.size = data_.o.capacity = count;
- }
-
- //! Initialize this value as constant string, without calling destructor.
- void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
- data_.f.flags = kConstStringFlag;
- SetStringPointer(s);
- data_.s.length = s.length;
- }
-
- //! Initialize this value as copy string with initial data, without calling destructor.
- void SetStringRaw(StringRefType s, Allocator& allocator) {
- Ch* str = 0;
- if (ShortString::Usable(s.length)) {
- data_.f.flags = kShortStringFlag;
- data_.ss.SetLength(s.length);
- str = data_.ss.str;
- } else {
- data_.f.flags = kCopyStringFlag;
- data_.s.length = s.length;
- str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)));
- SetStringPointer(str);
- }
- std::memcpy(str, s, s.length * sizeof(Ch));
- str[s.length] = '\0';
- }
-
- //! Assignment without calling destructor
- void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
- data_ = rhs.data_;
- // data_.f.flags = rhs.data_.f.flags;
- rhs.data_.f.flags = kNullFlag;
- }
-
- template <typename SourceAllocator>
- bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
- RAPIDJSON_ASSERT(IsString());
- RAPIDJSON_ASSERT(rhs.IsString());
-
- const SizeType len1 = GetStringLength();
- const SizeType len2 = rhs.GetStringLength();
- if(len1 != len2) { return false; }
-
- const Ch* const str1 = GetString();
- const Ch* const str2 = rhs.GetString();
- if(str1 == str2) { return true; } // fast path for constant string
-
- return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
- }
-
- Data data_;
-};
-
-//! GenericValue with UTF8 encoding
-typedef GenericValue<UTF8<> > Value;
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericDocument
-
-//! A document for parsing JSON text as DOM.
-/*!
- \note implements Handler concept
- \tparam Encoding Encoding for both parsing and string storage.
- \tparam Allocator Allocator for allocating memory for the DOM
- \tparam StackAllocator Allocator for allocating memory for stack during parsing.
- \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
-*/
-template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
-class GenericDocument : public GenericValue<Encoding, Allocator> {
-public:
- typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
- typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
- typedef Allocator AllocatorType; //!< Allocator type from template parameter.
-
- //! Constructor
- /*! Creates an empty document of specified type.
- \param type Mandatory type of object to create.
- \param allocator Optional allocator for allocating memory.
- \param stackCapacity Optional initial capacity of stack in bytes.
- \param stackAllocator Optional allocator for allocating memory for stack.
- */
- explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
- GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
- {
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
- }
-
- //! Constructor
- /*! Creates an empty document which type is Null.
- \param allocator Optional allocator for allocating memory.
- \param stackCapacity Optional initial capacity of stack in bytes.
- \param stackAllocator Optional allocator for allocating memory for stack.
- */
- GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
- allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
- {
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move constructor in C++11
- GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
- : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid prohibited move from Document
- allocator_(rhs.allocator_),
- ownAllocator_(rhs.ownAllocator_),
- stack_(std::move(rhs.stack_)),
- parseResult_(rhs.parseResult_)
- {
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.parseResult_ = ParseResult();
- }
-#endif
-
- ~GenericDocument() {
- Destroy();
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move assignment in C++11
- GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
- {
- // The cast to ValueType is necessary here, because otherwise it would
- // attempt to call GenericValue's templated assignment operator.
- ValueType::operator=(std::forward<ValueType>(rhs));
-
- // Calling the destructor here would prematurely call stack_'s destructor
- Destroy();
-
- allocator_ = rhs.allocator_;
- ownAllocator_ = rhs.ownAllocator_;
- stack_ = std::move(rhs.stack_);
- parseResult_ = rhs.parseResult_;
-
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.parseResult_ = ParseResult();
-
- return *this;
- }
-#endif
-
- //! Exchange the contents of this document with those of another.
- /*!
- \param rhs Another document.
- \note Constant complexity.
- \see GenericValue::Swap
- */
- GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
- ValueType::Swap(rhs);
- stack_.Swap(rhs.stack_);
- internal::Swap(allocator_, rhs.allocator_);
- internal::Swap(ownAllocator_, rhs.ownAllocator_);
- internal::Swap(parseResult_, rhs.parseResult_);
- return *this;
- }
-
- //! free-standing swap function helper
- /*!
- Helper function to enable support for common swap implementation pattern based on \c std::swap:
- \code
- void swap(MyClass& a, MyClass& b) {
- using std::swap;
- swap(a.doc, b.doc);
- // ...
- }
- \endcode
- \see Swap()
- */
- friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
-
- //! Populate this document by a generator which produces SAX events.
- /*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
- \param g Generator functor which sends SAX events to the parameter.
- \return The document itself for fluent API.
- */
- template <typename Generator>
- GenericDocument& Populate(Generator& g) {
- ClearStackOnExit scope(*this);
- if (g(*this)) {
- RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
- ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
- }
- return *this;
- }
-
- //!@name Parse from stream
- //!@{
-
- //! Parse JSON text from an input stream (with Encoding conversion)
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \tparam SourceEncoding Encoding of input stream
- \tparam InputStream Type of input stream, implementing Stream concept
- \param is Input stream to be parsed.
- \return The document itself for fluent API.
- */
- template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
- GenericDocument& ParseStream(InputStream& is) {
- GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
- stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
- ClearStackOnExit scope(*this);
- parseResult_ = reader.template Parse<parseFlags>(is, *this);
- if (parseResult_) {
- RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
- ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move value from stack to document
- }
- return *this;
- }
-
- //! Parse JSON text from an input stream
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \tparam InputStream Type of input stream, implementing Stream concept
- \param is Input stream to be parsed.
- \return The document itself for fluent API.
- */
- template <unsigned parseFlags, typename InputStream>
- GenericDocument& ParseStream(InputStream& is) {
- return ParseStream<parseFlags, Encoding, InputStream>(is);
- }
-
- //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
- /*! \tparam InputStream Type of input stream, implementing Stream concept
- \param is Input stream to be parsed.
- \return The document itself for fluent API.
- */
- template <typename InputStream>
- GenericDocument& ParseStream(InputStream& is) {
- return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
- }
- //!@}
-
- //!@name Parse in-place from mutable string
- //!@{
-
- //! Parse JSON text from a mutable string
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \param str Mutable zero-terminated string to be parsed.
- \return The document itself for fluent API.
- */
- template <unsigned parseFlags>
- GenericDocument& ParseInsitu(Ch* str) {
- GenericInsituStringStream<Encoding> s(str);
- return ParseStream<parseFlags | kParseInsituFlag>(s);
- }
-
- //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
- /*! \param str Mutable zero-terminated string to be parsed.
- \return The document itself for fluent API.
- */
- GenericDocument& ParseInsitu(Ch* str) {
- return ParseInsitu<kParseDefaultFlags>(str);
- }
- //!@}
-
- //!@name Parse from read-only string
- //!@{
-
- //! Parse JSON text from a read-only string (with Encoding conversion)
- /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
- \tparam SourceEncoding Transcoding from input Encoding
- \param str Read-only zero-terminated string to be parsed.
- */
- template <unsigned parseFlags, typename SourceEncoding>
- GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
- RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
- GenericStringStream<SourceEncoding> s(str);
- return ParseStream<parseFlags, SourceEncoding>(s);
- }
-
- //! Parse JSON text from a read-only string
- /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
- \param str Read-only zero-terminated string to be parsed.
- */
- template <unsigned parseFlags>
- GenericDocument& Parse(const Ch* str) {
- return Parse<parseFlags, Encoding>(str);
- }
-
- //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
- /*! \param str Read-only zero-terminated string to be parsed.
- */
- GenericDocument& Parse(const Ch* str) {
- return Parse<kParseDefaultFlags>(str);
- }
-
- template <unsigned parseFlags, typename SourceEncoding>
- GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
- RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
- MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
- EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
- ParseStream<parseFlags, SourceEncoding>(is);
- return *this;
- }
-
- template <unsigned parseFlags>
- GenericDocument& Parse(const Ch* str, size_t length) {
- return Parse<parseFlags, Encoding>(str, length);
- }
-
- GenericDocument& Parse(const Ch* str, size_t length) {
- return Parse<kParseDefaultFlags>(str, length);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- template <unsigned parseFlags, typename SourceEncoding>
- GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>& str) {
- // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t)
- return Parse<parseFlags, SourceEncoding>(str.c_str());
- }
-
- template <unsigned parseFlags>
- GenericDocument& Parse(const std::basic_string<Ch>& str) {
- return Parse<parseFlags, Encoding>(str.c_str());
- }
-
- GenericDocument& Parse(const std::basic_string<Ch>& str) {
- return Parse<kParseDefaultFlags>(str);
- }
-#endif // RAPIDJSON_HAS_STDSTRING
-
- //!@}
-
- //!@name Handling parse errors
- //!@{
-
- //! Whether a parse error has occured in the last parsing.
- bool HasParseError() const { return parseResult_.IsError(); }
-
- //! Get the \ref ParseErrorCode of last parsing.
- ParseErrorCode GetParseError() const { return parseResult_.Code(); }
-
- //! Get the position of last parsing error in input, 0 otherwise.
- size_t GetErrorOffset() const { return parseResult_.Offset(); }
-
- //! Implicit conversion to get the last parse result
-#ifndef __clang // -Wdocumentation
- /*! \return \ref ParseResult of the last parse operation
-
- \code
- Document doc;
- ParseResult ok = doc.Parse(json);
- if (!ok)
- printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset());
- \endcode
- */
-#endif
- operator ParseResult() const { return parseResult_; }
- //!@}
-
- //! Get the allocator of this document.
- Allocator& GetAllocator() {
- RAPIDJSON_ASSERT(allocator_);
- return *allocator_;
- }
-
- //! Get the capacity of stack in bytes.
- size_t GetStackCapacity() const { return stack_.GetCapacity(); }
-
-private:
- // clear stack on any exit from ParseStream, e.g. due to exception
- struct ClearStackOnExit {
- explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
- ~ClearStackOnExit() { d_.ClearStack(); }
- private:
- ClearStackOnExit(const ClearStackOnExit&);
- ClearStackOnExit& operator=(const ClearStackOnExit&);
- GenericDocument& d_;
- };
-
- // callers of the following private Handler functions
- // template <typename,typename,typename> friend class GenericReader; // for parsing
- template <typename, typename> friend class GenericValue; // for deep copying
-
-public:
- // Implementation of Handler
- bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
- bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
- bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
-
- bool RawNumber(const Ch* str, SizeType length, bool copy) {
- if (copy)
- new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
- else
- new (stack_.template Push<ValueType>()) ValueType(str, length);
- return true;
- }
-
- bool String(const Ch* str, SizeType length, bool copy) {
- if (copy)
- new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
- else
- new (stack_.template Push<ValueType>()) ValueType(str, length);
- return true;
- }
-
- bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
-
- bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
-
- bool EndObject(SizeType memberCount) {
- typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
- stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, GetAllocator());
- return true;
- }
-
- bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
-
- bool EndArray(SizeType elementCount) {
- ValueType* elements = stack_.template Pop<ValueType>(elementCount);
- stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
- return true;
- }
-
-private:
- //! Prohibit copying
- GenericDocument(const GenericDocument&);
- //! Prohibit assignment
- GenericDocument& operator=(const GenericDocument&);
-
- void ClearStack() {
- if (Allocator::kNeedFree)
- while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
- (stack_.template Pop<ValueType>(1))->~ValueType();
- else
- stack_.Clear();
- stack_.ShrinkToFit();
- }
-
- void Destroy() {
- RAPIDJSON_DELETE(ownAllocator_);
- }
-
- static const size_t kDefaultStackCapacity = 1024;
- Allocator* allocator_;
- Allocator* ownAllocator_;
- internal::Stack<StackAllocator> stack_;
- ParseResult parseResult_;
-};
-
-//! GenericDocument with UTF8 encoding
-typedef GenericDocument<UTF8<> > Document;
-
-// defined here due to the dependency on GenericDocument
-template <typename Encoding, typename Allocator>
-template <typename SourceAllocator>
-inline
-GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
-{
- switch (rhs.GetType()) {
- case kObjectType:
- case kArrayType: { // perform deep copy via SAX Handler
- GenericDocument<Encoding,Allocator> d(&allocator);
- rhs.Accept(d);
- RawAssign(*d.stack_.template Pop<GenericValue>(1));
- }
- break;
- case kStringType:
- if (rhs.data_.f.flags == kConstStringFlag) {
- data_.f.flags = rhs.data_.f.flags;
- data_ = *reinterpret_cast<const Data*>(&rhs.data_);
- } else {
- SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
- }
- break;
- default:
- data_.f.flags = rhs.data_.f.flags;
- data_ = *reinterpret_cast<const Data*>(&rhs.data_);
- break;
- }
-}
-
-//! Helper class for accessing Value of array type.
-/*!
- Instance of this helper class is obtained by \c GenericValue::GetArray().
- In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
-*/
-template <bool Const, typename ValueT>
-class GenericArray {
-public:
- typedef GenericArray<true, ValueT> ConstArray;
- typedef GenericArray<false, ValueT> Array;
- typedef ValueT PlainType;
- typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
- typedef ValueType* ValueIterator; // This may be const or non-const iterator
- typedef const ValueT* ConstValueIterator;
- typedef typename ValueType::AllocatorType AllocatorType;
- typedef typename ValueType::StringRefType StringRefType;
-
- template <typename, typename>
- friend class GenericValue;
-
- GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
- GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; }
- ~GenericArray() {}
-
- SizeType Size() const { return value_.Size(); }
- SizeType Capacity() const { return value_.Capacity(); }
- bool Empty() const { return value_.Empty(); }
- void Clear() const { value_.Clear(); }
- ValueType& operator[](SizeType index) const { return value_[index]; }
- ValueIterator Begin() const { return value_.Begin(); }
- ValueIterator End() const { return value_.End(); }
- GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; }
- GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; }
- GenericArray PopBack() const { value_.PopBack(); return *this; }
- ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); }
- ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); }
-
-#if RAPIDJSON_HAS_CXX11_RANGE_FOR
- ValueIterator begin() const { return value_.Begin(); }
- ValueIterator end() const { return value_.End(); }
-#endif
-
-private:
- GenericArray();
- GenericArray(ValueType& value) : value_(value) {}
- ValueType& value_;
-};
-
-//! Helper class for accessing Value of object type.
-/*!
- Instance of this helper class is obtained by \c GenericValue::GetObject().
- In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
-*/
-template <bool Const, typename ValueT>
-class GenericObject {
-public:
- typedef GenericObject<true, ValueT> ConstObject;
- typedef GenericObject<false, ValueT> Object;
- typedef ValueT PlainType;
- typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
- typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename ValueT::AllocatorType> MemberIterator; // This may be const or non-const iterator
- typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename ValueT::AllocatorType> ConstMemberIterator;
- typedef typename ValueType::AllocatorType AllocatorType;
- typedef typename ValueType::StringRefType StringRefType;
- typedef typename ValueType::EncodingType EncodingType;
- typedef typename ValueType::Ch Ch;
-
- template <typename, typename>
- friend class GenericValue;
-
- GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
- GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; }
- ~GenericObject() {}
-
- SizeType MemberCount() const { return value_.MemberCount(); }
- bool ObjectEmpty() const { return value_.ObjectEmpty(); }
- template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
- template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
-#if RAPIDJSON_HAS_STDSTRING
- ValueType& operator[](const std::basic_string<Ch>& name) const { return value_[name]; }
-#endif
- MemberIterator MemberBegin() const { return value_.MemberBegin(); }
- MemberIterator MemberEnd() const { return value_.MemberEnd(); }
- bool HasMember(const Ch* name) const { return value_.HasMember(name); }
-#if RAPIDJSON_HAS_STDSTRING
- bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
-#endif
- template <typename SourceAllocator> bool HasMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.HasMember(name); }
- MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); }
- template <typename SourceAllocator> MemberIterator FindMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name); }
-#if RAPIDJSON_HAS_STDSTRING
- MemberIterator FindMember(const std::basic_string<Ch>& name) const { return value_.FindMember(name); }
-#endif
- GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
-#if RAPIDJSON_HAS_STDSTRING
- GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
-#endif
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
- void RemoveAllMembers() { return value_.RemoveAllMembers(); }
- bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
-#if RAPIDJSON_HAS_STDSTRING
- bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
-#endif
- template <typename SourceAllocator> bool RemoveMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
- MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); }
- MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); }
- MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); }
- bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
-#if RAPIDJSON_HAS_STDSTRING
- bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMember(ValueType(StringRef(name))); }
-#endif
- template <typename SourceAllocator> bool EraseMember(const GenericValue<EncodingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
-
-#if RAPIDJSON_HAS_CXX11_RANGE_FOR
- MemberIterator begin() const { return value_.MemberBegin(); }
- MemberIterator end() const { return value_.MemberEnd(); }
-#endif
-
-private:
- GenericObject();
- GenericObject(ValueType& value) : value_(value) {}
- ValueType& value_;
-};
-
-RAPIDJSON_NAMESPACE_END
-RAPIDJSON_DIAG_POP
-
-#endif // RAPIDJSON_DOCUMENT_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ENCODEDSTREAM_H_
-#define RAPIDJSON_ENCODEDSTREAM_H_
-
-#include "stream.h"
-#include "memorystream.h"
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Input byte stream wrapper with a statically bound encoding.
-/*!
- \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
- \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
-*/
-template <typename Encoding, typename InputByteStream>
-class EncodedInputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
-public:
- typedef typename Encoding::Ch Ch;
-
- EncodedInputStream(InputByteStream& is) : is_(is) {
- current_ = Encoding::TakeBOM(is_);
- }
-
- Ch Peek() const { return current_; }
- Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
- size_t Tell() const { return is_.Tell(); }
-
- // Not implemented
- void Put(Ch) { RAPIDJSON_ASSERT(false); }
- void Flush() { RAPIDJSON_ASSERT(false); }
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
-private:
- EncodedInputStream(const EncodedInputStream&);
- EncodedInputStream& operator=(const EncodedInputStream&);
-
- InputByteStream& is_;
- Ch current_;
-};
-
-//! Specialized for UTF8 MemoryStream.
-template <>
-class EncodedInputStream<UTF8<>, MemoryStream> {
-public:
- typedef UTF8<>::Ch Ch;
-
- EncodedInputStream(MemoryStream& is) : is_(is) {
- if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
- if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
- if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
- }
- Ch Peek() const { return is_.Peek(); }
- Ch Take() { return is_.Take(); }
- size_t Tell() const { return is_.Tell(); }
-
- // Not implemented
- void Put(Ch) {}
- void Flush() {}
- Ch* PutBegin() { return 0; }
- size_t PutEnd(Ch*) { return 0; }
-
- MemoryStream& is_;
-
-private:
- EncodedInputStream(const EncodedInputStream&);
- EncodedInputStream& operator=(const EncodedInputStream&);
-};
-
-//! Output byte stream wrapper with statically bound encoding.
-/*!
- \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
- \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream.
-*/
-template <typename Encoding, typename OutputByteStream>
-class EncodedOutputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
-public:
- typedef typename Encoding::Ch Ch;
-
- EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
- if (putBOM)
- Encoding::PutBOM(os_);
- }
-
- void Put(Ch c) { Encoding::Put(os_, c); }
- void Flush() { os_.Flush(); }
-
- // Not implemented
- Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
- Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
- size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
-private:
- EncodedOutputStream(const EncodedOutputStream&);
- EncodedOutputStream& operator=(const EncodedOutputStream&);
-
- OutputByteStream& os_;
-};
-
-#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
-
-//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
-/*!
- \tparam CharType Type of character for reading.
- \tparam InputByteStream type of input byte stream to be wrapped.
-*/
-template <typename CharType, typename InputByteStream>
-class AutoUTFInputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
-public:
- typedef CharType Ch;
-
- //! Constructor.
- /*!
- \param is input stream to be wrapped.
- \param type UTF encoding type if it is not detected from the stream.
- */
- AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
- RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
- DetectType();
- static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
- takeFunc_ = f[type_];
- current_ = takeFunc_(*is_);
- }
-
- UTFType GetType() const { return type_; }
- bool HasBOM() const { return hasBOM_; }
-
- Ch Peek() const { return current_; }
- Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
- size_t Tell() const { return is_->Tell(); }
-
- // Not implemented
- void Put(Ch) { RAPIDJSON_ASSERT(false); }
- void Flush() { RAPIDJSON_ASSERT(false); }
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
-private:
- AutoUTFInputStream(const AutoUTFInputStream&);
- AutoUTFInputStream& operator=(const AutoUTFInputStream&);
-
- // Detect encoding type with BOM or RFC 4627
- void DetectType() {
- // BOM (Byte Order Mark):
- // 00 00 FE FF UTF-32BE
- // FF FE 00 00 UTF-32LE
- // FE FF UTF-16BE
- // FF FE UTF-16LE
- // EF BB BF UTF-8
-
- const unsigned char* c = reinterpret_cast<const unsigned char *>(is_->Peek4());
- if (!c)
- return;
-
- unsigned bom = static_cast<unsigned>(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24));
- hasBOM_ = false;
- if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
- else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
- else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
- else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
- else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
-
- // RFC 4627: Section 3
- // "Since the first two characters of a JSON text will always be ASCII
- // characters [RFC0020], it is possible to determine whether an octet
- // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
- // at the pattern of nulls in the first four octets."
- // 00 00 00 xx UTF-32BE
- // 00 xx 00 xx UTF-16BE
- // xx 00 00 00 UTF-32LE
- // xx 00 xx 00 UTF-16LE
- // xx xx xx xx UTF-8
-
- if (!hasBOM_) {
- unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
- switch (pattern) {
- case 0x08: type_ = kUTF32BE; break;
- case 0x0A: type_ = kUTF16BE; break;
- case 0x01: type_ = kUTF32LE; break;
- case 0x05: type_ = kUTF16LE; break;
- case 0x0F: type_ = kUTF8; break;
- default: break; // Use type defined by user.
- }
- }
-
- // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
- if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
- if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
- }
-
- typedef Ch (*TakeFunc)(InputByteStream& is);
- InputByteStream* is_;
- UTFType type_;
- Ch current_;
- TakeFunc takeFunc_;
- bool hasBOM_;
-};
-
-//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
-/*!
- \tparam CharType Type of character for writing.
- \tparam OutputByteStream type of output byte stream to be wrapped.
-*/
-template <typename CharType, typename OutputByteStream>
-class AutoUTFOutputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
-public:
- typedef CharType Ch;
-
- //! Constructor.
- /*!
- \param os output stream to be wrapped.
- \param type UTF encoding type.
- \param putBOM Whether to write BOM at the beginning of the stream.
- */
- AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
- RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
-
- // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
- if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
- if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
-
- static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
- putFunc_ = f[type_];
-
- if (putBOM)
- PutBOM();
- }
-
- UTFType GetType() const { return type_; }
-
- void Put(Ch c) { putFunc_(*os_, c); }
- void Flush() { os_->Flush(); }
-
- // Not implemented
- Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
- Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
- size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
-private:
- AutoUTFOutputStream(const AutoUTFOutputStream&);
- AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
-
- void PutBOM() {
- typedef void (*PutBOMFunc)(OutputByteStream&);
- static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
- f[type_](*os_);
- }
-
- typedef void (*PutFunc)(OutputByteStream&, Ch);
-
- OutputByteStream* os_;
- UTFType type_;
- PutFunc putFunc_;
-};
-
-#undef RAPIDJSON_ENCODINGS_FUNC
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_FILESTREAM_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ENCODINGS_H_
-#define RAPIDJSON_ENCODINGS_H_
-
-#include "rapidjson.h"
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
-RAPIDJSON_DIAG_OFF(4702) // unreachable code
-#elif defined(__GNUC__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-RAPIDJSON_DIAG_OFF(overflow)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Encoding
-
-/*! \class rapidjson::Encoding
- \brief Concept for encoding of Unicode characters.
-
-\code
-concept Encoding {
- typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
-
- enum { supportUnicode = 1 }; // or 0 if not supporting unicode
-
- //! \brief Encode a Unicode codepoint to an output stream.
- //! \param os Output stream.
- //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint);
-
- //! \brief Decode a Unicode codepoint from an input stream.
- //! \param is Input stream.
- //! \param codepoint Output of the unicode codepoint.
- //! \return true if a valid codepoint can be decoded from the stream.
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint);
-
- //! \brief Validate one Unicode codepoint from an encoded stream.
- //! \param is Input stream to obtain codepoint.
- //! \param os Output for copying one codepoint.
- //! \return true if it is valid.
- //! \note This function just validating and copying the codepoint without actually decode it.
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os);
-
- // The following functions are deal with byte streams.
-
- //! Take a character from input byte stream, skip BOM if exist.
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is);
-
- //! Take a character from input byte stream.
- template <typename InputByteStream>
- static Ch Take(InputByteStream& is);
-
- //! Put BOM to output byte stream.
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os);
-
- //! Put a character to output byte stream.
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, Ch c);
-};
-\endcode
-*/
-
-///////////////////////////////////////////////////////////////////////////////
-// UTF8
-
-//! UTF-8 encoding.
-/*! http://en.wikipedia.org/wiki/UTF-8
- http://tools.ietf.org/html/rfc3629
- \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
- \note implements Encoding concept
-*/
-template<typename CharType = char>
-struct UTF8 {
- typedef CharType Ch;
-
- enum { supportUnicode = 1 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- if (codepoint <= 0x7F)
- os.Put(static_cast<Ch>(codepoint & 0xFF));
- else if (codepoint <= 0x7FF) {
- os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
- os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
- }
- else if (codepoint <= 0xFFFF) {
- os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
- os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
- os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
- }
- else {
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
- os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
- os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
- os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
- }
- }
-
- template<typename OutputStream>
- static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
- if (codepoint <= 0x7F)
- PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
- else if (codepoint <= 0x7FF) {
- PutUnsafe(os, static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
- PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
- }
- else if (codepoint <= 0xFFFF) {
- PutUnsafe(os, static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
- PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
- PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
- }
- else {
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
- PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
- PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
- PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
- }
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
-#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
-#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
-#define TAIL() COPY(); TRANS(0x70)
- typename InputStream::Ch c = is.Take();
- if (!(c & 0x80)) {
- *codepoint = static_cast<unsigned char>(c);
- return true;
- }
-
- unsigned char type = GetRange(static_cast<unsigned char>(c));
- if (type >= 32) {
- *codepoint = 0;
- } else {
- *codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
- }
- bool result = true;
- switch (type) {
- case 2: TAIL(); return result;
- case 3: TAIL(); TAIL(); return result;
- case 4: COPY(); TRANS(0x50); TAIL(); return result;
- case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
- case 6: TAIL(); TAIL(); TAIL(); return result;
- case 10: COPY(); TRANS(0x20); TAIL(); return result;
- case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
- default: return false;
- }
-#undef COPY
-#undef TRANS
-#undef TAIL
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
-#define COPY() os.Put(c = is.Take())
-#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
-#define TAIL() COPY(); TRANS(0x70)
- Ch c;
- COPY();
- if (!(c & 0x80))
- return true;
-
- bool result = true;
- switch (GetRange(static_cast<unsigned char>(c))) {
- case 2: TAIL(); return result;
- case 3: TAIL(); TAIL(); return result;
- case 4: COPY(); TRANS(0x50); TAIL(); return result;
- case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
- case 6: TAIL(); TAIL(); TAIL(); return result;
- case 10: COPY(); TRANS(0x20); TAIL(); return result;
- case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
- default: return false;
- }
-#undef COPY
-#undef TRANS
-#undef TAIL
- }
-
- static unsigned char GetRange(unsigned char c) {
- // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
- // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
- static const unsigned char type[] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
- 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
- 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
- 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
- 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
- };
- return type[c];
- }
-
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- typename InputByteStream::Ch c = Take(is);
- if (static_cast<unsigned char>(c) != 0xEFu) return c;
- c = is.Take();
- if (static_cast<unsigned char>(c) != 0xBBu) return c;
- c = is.Take();
- if (static_cast<unsigned char>(c) != 0xBFu) return c;
- c = is.Take();
- return c;
- }
-
- template <typename InputByteStream>
- static Ch Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- return static_cast<Ch>(is.Take());
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, Ch c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(c));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// UTF16
-
-//! UTF-16 encoding.
-/*! http://en.wikipedia.org/wiki/UTF-16
- http://tools.ietf.org/html/rfc2781
- \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
- \note implements Encoding concept
-
- \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
- For streaming, use UTF16LE and UTF16BE, which handle endianness.
-*/
-template<typename CharType = wchar_t>
-struct UTF16 {
- typedef CharType Ch;
- RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
-
- enum { supportUnicode = 1 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
- if (codepoint <= 0xFFFF) {
- RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
- os.Put(static_cast<typename OutputStream::Ch>(codepoint));
- }
- else {
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- unsigned v = codepoint - 0x10000;
- os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
- os.Put((v & 0x3FF) | 0xDC00);
- }
- }
-
-
- template<typename OutputStream>
- static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
- if (codepoint <= 0xFFFF) {
- RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
- PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
- }
- else {
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- unsigned v = codepoint - 0x10000;
- PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
- PutUnsafe(os, (v & 0x3FF) | 0xDC00);
- }
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
- typename InputStream::Ch c = is.Take();
- if (c < 0xD800 || c > 0xDFFF) {
- *codepoint = static_cast<unsigned>(c);
- return true;
- }
- else if (c <= 0xDBFF) {
- *codepoint = (static_cast<unsigned>(c) & 0x3FF) << 10;
- c = is.Take();
- *codepoint |= (static_cast<unsigned>(c) & 0x3FF);
- *codepoint += 0x10000;
- return c >= 0xDC00 && c <= 0xDFFF;
- }
- return false;
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
- typename InputStream::Ch c;
- os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
- if (c < 0xD800 || c > 0xDFFF)
- return true;
- else if (c <= 0xDBFF) {
- os.Put(c = is.Take());
- return c >= 0xDC00 && c <= 0xDFFF;
- }
- return false;
- }
-};
-
-//! UTF-16 little endian encoding.
-template<typename CharType = wchar_t>
-struct UTF16LE : UTF16<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- unsigned c = static_cast<uint8_t>(is.Take());
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
- return static_cast<CharType>(c);
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
- }
-};
-
-//! UTF-16 big endian encoding.
-template<typename CharType = wchar_t>
-struct UTF16BE : UTF16<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
- c |= static_cast<uint8_t>(is.Take());
- return static_cast<CharType>(c);
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// UTF32
-
-//! UTF-32 encoding.
-/*! http://en.wikipedia.org/wiki/UTF-32
- \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
- \note implements Encoding concept
-
- \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
- For streaming, use UTF32LE and UTF32BE, which handle endianness.
-*/
-template<typename CharType = unsigned>
-struct UTF32 {
- typedef CharType Ch;
- RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
-
- enum { supportUnicode = 1 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- os.Put(codepoint);
- }
-
- template<typename OutputStream>
- static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- PutUnsafe(os, codepoint);
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
- Ch c = is.Take();
- *codepoint = c;
- return c <= 0x10FFFF;
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
- Ch c;
- os.Put(c = is.Take());
- return c <= 0x10FFFF;
- }
-};
-
-//! UTF-32 little endian enocoding.
-template<typename CharType = unsigned>
-struct UTF32LE : UTF32<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- unsigned c = static_cast<uint8_t>(is.Take());
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
- return static_cast<CharType>(c);
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
- os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
- }
-};
-
-//! UTF-32 big endian encoding.
-template<typename CharType = unsigned>
-struct UTF32BE : UTF32<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
- c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
- return static_cast<CharType>(c);
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
- os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
- os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
- os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// ASCII
-
-//! ASCII encoding.
-/*! http://en.wikipedia.org/wiki/ASCII
- \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
- \note implements Encoding concept
-*/
-template<typename CharType = char>
-struct ASCII {
- typedef CharType Ch;
-
- enum { supportUnicode = 0 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_ASSERT(codepoint <= 0x7F);
- os.Put(static_cast<Ch>(codepoint & 0xFF));
- }
-
- template<typename OutputStream>
- static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_ASSERT(codepoint <= 0x7F);
- PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
- uint8_t c = static_cast<uint8_t>(is.Take());
- *codepoint = c;
- return c <= 0X7F;
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
- uint8_t c = static_cast<uint8_t>(is.Take());
- os.Put(static_cast<typename OutputStream::Ch>(c));
- return c <= 0x7F;
- }
-
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- uint8_t c = static_cast<uint8_t>(Take(is));
- return static_cast<Ch>(c);
- }
-
- template <typename InputByteStream>
- static Ch Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- return static_cast<Ch>(is.Take());
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- (void)os;
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, Ch c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(c));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// AutoUTF
-
-//! Runtime-specified UTF encoding type of a stream.
-enum UTFType {
- kUTF8 = 0, //!< UTF-8.
- kUTF16LE = 1, //!< UTF-16 little endian.
- kUTF16BE = 2, //!< UTF-16 big endian.
- kUTF32LE = 3, //!< UTF-32 little endian.
- kUTF32BE = 4 //!< UTF-32 big endian.
-};
-
-//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
-/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
-*/
-template<typename CharType>
-struct AutoUTF {
- typedef CharType Ch;
-
- enum { supportUnicode = 1 };
-
-#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
-
- template<typename OutputStream>
- RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
- typedef void (*EncodeFunc)(OutputStream&, unsigned);
- static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
- (*f[os.GetType()])(os, codepoint);
- }
-
- template<typename OutputStream>
- RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
- typedef void (*EncodeFunc)(OutputStream&, unsigned);
- static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
- (*f[os.GetType()])(os, codepoint);
- }
-
- template <typename InputStream>
- RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
- typedef bool (*DecodeFunc)(InputStream&, unsigned*);
- static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
- return (*f[is.GetType()])(is, codepoint);
- }
-
- template <typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
- typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
- static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
- return (*f[is.GetType()])(is, os);
- }
-
-#undef RAPIDJSON_ENCODINGS_FUNC
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Transcoder
-
-//! Encoding conversion.
-template<typename SourceEncoding, typename TargetEncoding>
-struct Transcoder {
- //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
- unsigned codepoint;
- if (!SourceEncoding::Decode(is, &codepoint))
- return false;
- TargetEncoding::Encode(os, codepoint);
- return true;
- }
-
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
- unsigned codepoint;
- if (!SourceEncoding::Decode(is, &codepoint))
- return false;
- TargetEncoding::EncodeUnsafe(os, codepoint);
- return true;
- }
-
- //! Validate one Unicode codepoint from an encoded stream.
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
- return Transcode(is, os); // Since source/target encoding is different, must transcode.
- }
-};
-
-// Forward declaration.
-template<typename Stream>
-inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
-
-//! Specialization of Transcoder with same source and target encoding.
-template<typename Encoding>
-struct Transcoder<Encoding, Encoding> {
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
- os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
- return true;
- }
-
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
- PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
- return true;
- }
-
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
- return Encoding::Validate(is, os); // source/target encoding are the same
- }
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#if defined(__GNUC__) || defined(_MSC_VER)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_ENCODINGS_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ERROR_EN_H_
-#define RAPIDJSON_ERROR_EN_H_
-
-#include "error.h"
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(switch-enum)
-RAPIDJSON_DIAG_OFF(covered-switch-default)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Maps error code of parsing into error message.
-/*!
- \ingroup RAPIDJSON_ERRORS
- \param parseErrorCode Error code obtained in parsing.
- \return the error message.
- \note User can make a copy of this function for localization.
- Using switch-case is safer for future modification of error codes.
-*/
-inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
- switch (parseErrorCode) {
- case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
-
- case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
- case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
-
- case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
-
- case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
- case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
- case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
-
- case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
-
- case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
- case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
- case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
- case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
- case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
-
- case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
- case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
- case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
-
- case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
- case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
-
- default: return RAPIDJSON_ERROR_STRING("Unknown error.");
- }
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_ERROR_EN_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ERROR_ERROR_H_
-#define RAPIDJSON_ERROR_ERROR_H_
-
-#include "../rapidjson.h"
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-#endif
-
-/*! \file error.h */
-
-/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ERROR_CHARTYPE
-
-//! Character type of error messages.
-/*! \ingroup RAPIDJSON_ERRORS
- The default character type is \c char.
- On Windows, user can define this macro as \c TCHAR for supporting both
- unicode/non-unicode settings.
-*/
-#ifndef RAPIDJSON_ERROR_CHARTYPE
-#define RAPIDJSON_ERROR_CHARTYPE char
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ERROR_STRING
-
-//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
-/*! \ingroup RAPIDJSON_ERRORS
- By default this conversion macro does nothing.
- On Windows, user can define this macro as \c _T(x) for supporting both
- unicode/non-unicode settings.
-*/
-#ifndef RAPIDJSON_ERROR_STRING
-#define RAPIDJSON_ERROR_STRING(x) x
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// ParseErrorCode
-
-//! Error code of parsing.
-/*! \ingroup RAPIDJSON_ERRORS
- \see GenericReader::Parse, GenericReader::GetParseErrorCode
-*/
-enum ParseErrorCode {
- kParseErrorNone = 0, //!< No error.
-
- kParseErrorDocumentEmpty, //!< The document is empty.
- kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values.
-
- kParseErrorValueInvalid, //!< Invalid value.
-
- kParseErrorObjectMissName, //!< Missing a name for object member.
- kParseErrorObjectMissColon, //!< Missing a colon after a name of object member.
- kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member.
-
- kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element.
-
- kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string.
- kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid.
- kParseErrorStringEscapeInvalid, //!< Invalid escape character in string.
- kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string.
- kParseErrorStringInvalidEncoding, //!< Invalid encoding in string.
-
- kParseErrorNumberTooBig, //!< Number too big to be stored in double.
- kParseErrorNumberMissFraction, //!< Miss fraction part in number.
- kParseErrorNumberMissExponent, //!< Miss exponent in number.
-
- kParseErrorTermination, //!< Parsing was terminated.
- kParseErrorUnspecificSyntaxError //!< Unspecific syntax error.
-};
-
-//! Result of parsing (wraps ParseErrorCode)
-/*!
- \ingroup RAPIDJSON_ERRORS
- \code
- Document doc;
- ParseResult ok = doc.Parse("[42]");
- if (!ok) {
- fprintf(stderr, "JSON parse error: %s (%u)",
- GetParseError_En(ok.Code()), ok.Offset());
- exit(EXIT_FAILURE);
- }
- \endcode
- \see GenericReader::Parse, GenericDocument::Parse
-*/
-struct ParseResult {
-public:
- //! Default constructor, no error.
- ParseResult() : code_(kParseErrorNone), offset_(0) {}
- //! Constructor to set an error.
- ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {}
-
- //! Get the error code.
- ParseErrorCode Code() const { return code_; }
- //! Get the error offset, if \ref IsError(), 0 otherwise.
- size_t Offset() const { return offset_; }
-
- //! Conversion to \c bool, returns \c true, iff !\ref IsError().
- operator bool() const { return !IsError(); }
- //! Whether the result is an error.
- bool IsError() const { return code_ != kParseErrorNone; }
-
- bool operator==(const ParseResult& that) const { return code_ == that.code_; }
- bool operator==(ParseErrorCode code) const { return code_ == code; }
- friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
-
- //! Reset error code.
- void Clear() { Set(kParseErrorNone); }
- //! Update error code and offset.
- void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; }
-
-private:
- ParseErrorCode code_;
- size_t offset_;
-};
-
-//! Function pointer type of GetParseError().
-/*! \ingroup RAPIDJSON_ERRORS
-
- This is the prototype for \c GetParseError_X(), where \c X is a locale.
- User can dynamically change locale in runtime, e.g.:
-\code
- GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
- const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
-\endcode
-*/
-typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_ERROR_ERROR_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_FILEREADSTREAM_H_
-#define RAPIDJSON_FILEREADSTREAM_H_
-
-#include "stream.h"
-#include <cstdio>
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-RAPIDJSON_DIAG_OFF(unreachable-code)
-RAPIDJSON_DIAG_OFF(missing-noreturn)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! File byte stream for input using fread().
-/*!
- \note implements Stream concept
-*/
-class FileReadStream {
-public:
- typedef char Ch; //!< Character type (byte).
-
- //! Constructor.
- /*!
- \param fp File pointer opened for read.
- \param buffer user-supplied buffer.
- \param bufferSize size of buffer in bytes. Must >=4 bytes.
- */
- FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
- RAPIDJSON_ASSERT(fp_ != 0);
- RAPIDJSON_ASSERT(bufferSize >= 4);
- Read();
- }
-
- Ch Peek() const { return *current_; }
- Ch Take() { Ch c = *current_; Read(); return c; }
- size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
-
- // Not implemented
- void Put(Ch) { RAPIDJSON_ASSERT(false); }
- void Flush() { RAPIDJSON_ASSERT(false); }
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
- // For encoding detection only.
- const Ch* Peek4() const {
- return (current_ + 4 <= bufferLast_) ? current_ : 0;
- }
-
-private:
- void Read() {
- if (current_ < bufferLast_)
- ++current_;
- else if (!eof_) {
- count_ += readCount_;
- readCount_ = fread(buffer_, 1, bufferSize_, fp_);
- bufferLast_ = buffer_ + readCount_ - 1;
- current_ = buffer_;
-
- if (readCount_ < bufferSize_) {
- buffer_[readCount_] = '\0';
- ++bufferLast_;
- eof_ = true;
- }
- }
- }
-
- std::FILE* fp_;
- Ch *buffer_;
- size_t bufferSize_;
- Ch *bufferLast_;
- Ch *current_;
- size_t readCount_;
- size_t count_; //!< Number of characters read
- bool eof_;
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_FILESTREAM_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_FILEWRITESTREAM_H_
-#define RAPIDJSON_FILEWRITESTREAM_H_
-
-#include "stream.h"
-#include <cstdio>
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(unreachable-code)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Wrapper of C file stream for input using fread().
-/*!
- \note implements Stream concept
-*/
-class FileWriteStream {
-public:
- typedef char Ch; //!< Character type. Only support char.
-
- FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
- RAPIDJSON_ASSERT(fp_ != 0);
- }
-
- void Put(char c) {
- if (current_ >= bufferEnd_)
- Flush();
-
- *current_++ = c;
- }
-
- void PutN(char c, size_t n) {
- size_t avail = static_cast<size_t>(bufferEnd_ - current_);
- while (n > avail) {
- std::memset(current_, c, avail);
- current_ += avail;
- Flush();
- n -= avail;
- avail = static_cast<size_t>(bufferEnd_ - current_);
- }
-
- if (n > 0) {
- std::memset(current_, c, n);
- current_ += n;
- }
- }
-
- void Flush() {
- if (current_ != buffer_) {
- size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
- if (result < static_cast<size_t>(current_ - buffer_)) {
- // failure deliberately ignored at this time
- // added to avoid warn_unused_result build errors
- }
- current_ = buffer_;
- }
- }
-
- // Not implemented
- char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
- char Take() { RAPIDJSON_ASSERT(false); return 0; }
- size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
- char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
-
-private:
- // Prohibit copy constructor & assignment operator.
- FileWriteStream(const FileWriteStream&);
- FileWriteStream& operator=(const FileWriteStream&);
-
- std::FILE* fp_;
- char *buffer_;
- char *bufferEnd_;
- char *current_;
-};
-
-//! Implement specialized version of PutN() with memset() for better performance.
-template<>
-inline void PutN(FileWriteStream& stream, char c, size_t n) {
- stream.PutN(c, n);
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_FILESTREAM_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_FWD_H_
-#define RAPIDJSON_FWD_H_
-
-#include "rapidjson.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-// encodings.h
-
-template<typename CharType> struct UTF8;
-template<typename CharType> struct UTF16;
-template<typename CharType> struct UTF16BE;
-template<typename CharType> struct UTF16LE;
-template<typename CharType> struct UTF32;
-template<typename CharType> struct UTF32BE;
-template<typename CharType> struct UTF32LE;
-template<typename CharType> struct ASCII;
-template<typename CharType> struct AutoUTF;
-
-template<typename SourceEncoding, typename TargetEncoding>
-struct Transcoder;
-
-// allocators.h
-
-class CrtAllocator;
-
-template <typename BaseAllocator>
-class MemoryPoolAllocator;
-
-// stream.h
-
-template <typename Encoding>
-struct GenericStringStream;
-
-typedef GenericStringStream<UTF8<char> > StringStream;
-
-template <typename Encoding>
-struct GenericInsituStringStream;
-
-typedef GenericInsituStringStream<UTF8<char> > InsituStringStream;
-
-// stringbuffer.h
-
-template <typename Encoding, typename Allocator>
-class GenericStringBuffer;
-
-typedef GenericStringBuffer<UTF8<char>, CrtAllocator> StringBuffer;
-
-// filereadstream.h
-
-class FileReadStream;
-
-// filewritestream.h
-
-class FileWriteStream;
-
-// memorybuffer.h
-
-template <typename Allocator>
-struct GenericMemoryBuffer;
-
-typedef GenericMemoryBuffer<CrtAllocator> MemoryBuffer;
-
-// memorystream.h
-
-struct MemoryStream;
-
-// reader.h
-
-template<typename Encoding, typename Derived>
-struct BaseReaderHandler;
-
-template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator>
-class GenericReader;
-
-typedef GenericReader<UTF8<char>, UTF8<char>, CrtAllocator> Reader;
-
-// writer.h
-
-template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
-class Writer;
-
-// prettywriter.h
-
-template<typename OutputStream, typename SourceEncoding, typename TargetEncoding, typename StackAllocator, unsigned writeFlags>
-class PrettyWriter;
-
-// document.h
-
-template <typename Encoding, typename Allocator>
-struct GenericMember;
-
-template <bool Const, typename Encoding, typename Allocator>
-class GenericMemberIterator;
-
-template<typename CharType>
-struct GenericStringRef;
-
-template <typename Encoding, typename Allocator>
-class GenericValue;
-
-typedef GenericValue<UTF8<char>, MemoryPoolAllocator<CrtAllocator> > Value;
-
-template <typename Encoding, typename Allocator, typename StackAllocator>
-class GenericDocument;
-
-typedef GenericDocument<UTF8<char>, MemoryPoolAllocator<CrtAllocator>, CrtAllocator> Document;
-
-// pointer.h
-
-template <typename ValueType, typename Allocator>
-class GenericPointer;
-
-typedef GenericPointer<Value, CrtAllocator> Pointer;
-
-// schema.h
-
-template <typename SchemaDocumentType>
-class IGenericRemoteSchemaDocumentProvider;
-
-template <typename ValueT, typename Allocator>
-class GenericSchemaDocument;
-
-typedef GenericSchemaDocument<Value, CrtAllocator> SchemaDocument;
-typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
-
-template <
- typename SchemaDocumentType,
- typename OutputHandler,
- typename StateAllocator>
-class GenericSchemaValidator;
-
-typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_RAPIDJSONFWD_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_BIGINTEGER_H_
-#define RAPIDJSON_BIGINTEGER_H_
-
-#include "../rapidjson.h"
-
-#if defined(_MSC_VER) && defined(_M_AMD64)
-#include <intrin.h> // for _umul128
-#pragma intrinsic(_umul128)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-class BigInteger {
-public:
- typedef uint64_t Type;
-
- BigInteger(const BigInteger& rhs) : count_(rhs.count_) {
- std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
- }
-
- explicit BigInteger(uint64_t u) : count_(1) {
- digits_[0] = u;
- }
-
- BigInteger(const char* decimals, size_t length) : count_(1) {
- RAPIDJSON_ASSERT(length > 0);
- digits_[0] = 0;
- size_t i = 0;
- const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
- while (length >= kMaxDigitPerIteration) {
- AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration);
- length -= kMaxDigitPerIteration;
- i += kMaxDigitPerIteration;
- }
-
- if (length > 0)
- AppendDecimal64(decimals + i, decimals + i + length);
- }
-
- BigInteger& operator=(const BigInteger &rhs)
- {
- if (this != &rhs) {
- count_ = rhs.count_;
- std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type));
- }
- return *this;
- }
-
- BigInteger& operator=(uint64_t u) {
- digits_[0] = u;
- count_ = 1;
- return *this;
- }
-
- BigInteger& operator+=(uint64_t u) {
- Type backup = digits_[0];
- digits_[0] += u;
- for (size_t i = 0; i < count_ - 1; i++) {
- if (digits_[i] >= backup)
- return *this; // no carry
- backup = digits_[i + 1];
- digits_[i + 1] += 1;
- }
-
- // Last carry
- if (digits_[count_ - 1] < backup)
- PushBack(1);
-
- return *this;
- }
-
- BigInteger& operator*=(uint64_t u) {
- if (u == 0) return *this = 0;
- if (u == 1) return *this;
- if (*this == 1) return *this = u;
-
- uint64_t k = 0;
- for (size_t i = 0; i < count_; i++) {
- uint64_t hi;
- digits_[i] = MulAdd64(digits_[i], u, k, &hi);
- k = hi;
- }
-
- if (k > 0)
- PushBack(k);
-
- return *this;
- }
-
- BigInteger& operator*=(uint32_t u) {
- if (u == 0) return *this = 0;
- if (u == 1) return *this;
- if (*this == 1) return *this = u;
-
- uint64_t k = 0;
- for (size_t i = 0; i < count_; i++) {
- const uint64_t c = digits_[i] >> 32;
- const uint64_t d = digits_[i] & 0xFFFFFFFF;
- const uint64_t uc = u * c;
- const uint64_t ud = u * d;
- const uint64_t p0 = ud + k;
- const uint64_t p1 = uc + (p0 >> 32);
- digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32);
- k = p1 >> 32;
- }
-
- if (k > 0)
- PushBack(k);
-
- return *this;
- }
-
- BigInteger& operator<<=(size_t shift) {
- if (IsZero() || shift == 0) return *this;
-
- size_t offset = shift / kTypeBit;
- size_t interShift = shift % kTypeBit;
- RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
-
- if (interShift == 0) {
- std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
- count_ += offset;
- }
- else {
- digits_[count_] = 0;
- for (size_t i = count_; i > 0; i--)
- digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift));
- digits_[offset] = digits_[0] << interShift;
- count_ += offset;
- if (digits_[count_])
- count_++;
- }
-
- std::memset(digits_, 0, offset * sizeof(Type));
-
- return *this;
- }
-
- bool operator==(const BigInteger& rhs) const {
- return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0;
- }
-
- bool operator==(const Type rhs) const {
- return count_ == 1 && digits_[0] == rhs;
- }
-
- BigInteger& MultiplyPow5(unsigned exp) {
- static const uint32_t kPow5[12] = {
- 5,
- 5 * 5,
- 5 * 5 * 5,
- 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
- };
- if (exp == 0) return *this;
- for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
- for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
- if (exp > 0) *this *= kPow5[exp - 1];
- return *this;
- }
-
- // Compute absolute difference of this and rhs.
- // Assume this != rhs
- bool Difference(const BigInteger& rhs, BigInteger* out) const {
- int cmp = Compare(rhs);
- RAPIDJSON_ASSERT(cmp != 0);
- const BigInteger *a, *b; // Makes a > b
- bool ret;
- if (cmp < 0) { a = &rhs; b = this; ret = true; }
- else { a = this; b = &rhs; ret = false; }
-
- Type borrow = 0;
- for (size_t i = 0; i < a->count_; i++) {
- Type d = a->digits_[i] - borrow;
- if (i < b->count_)
- d -= b->digits_[i];
- borrow = (d > a->digits_[i]) ? 1 : 0;
- out->digits_[i] = d;
- if (d != 0)
- out->count_ = i + 1;
- }
-
- return ret;
- }
-
- int Compare(const BigInteger& rhs) const {
- if (count_ != rhs.count_)
- return count_ < rhs.count_ ? -1 : 1;
-
- for (size_t i = count_; i-- > 0;)
- if (digits_[i] != rhs.digits_[i])
- return digits_[i] < rhs.digits_[i] ? -1 : 1;
-
- return 0;
- }
-
- size_t GetCount() const { return count_; }
- Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
- bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
-
-private:
- void AppendDecimal64(const char* begin, const char* end) {
- uint64_t u = ParseUint64(begin, end);
- if (IsZero())
- *this = u;
- else {
- unsigned exp = static_cast<unsigned>(end - begin);
- (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u
- }
- }
-
- void PushBack(Type digit) {
- RAPIDJSON_ASSERT(count_ < kCapacity);
- digits_[count_++] = digit;
- }
-
- static uint64_t ParseUint64(const char* begin, const char* end) {
- uint64_t r = 0;
- for (const char* p = begin; p != end; ++p) {
- RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
- r = r * 10u + static_cast<unsigned>(*p - '0');
- }
- return r;
- }
-
- // Assume a * b + k < 2^128
- static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) {
-#if defined(_MSC_VER) && defined(_M_AMD64)
- uint64_t low = _umul128(a, b, outHigh) + k;
- if (low < k)
- (*outHigh)++;
- return low;
-#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
- __extension__ typedef unsigned __int128 uint128;
- uint128 p = static_cast<uint128>(a) * static_cast<uint128>(b);
- p += k;
- *outHigh = static_cast<uint64_t>(p >> 64);
- return static_cast<uint64_t>(p);
-#else
- const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32;
- uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1;
- x1 += (x0 >> 32); // can't give carry
- x1 += x2;
- if (x1 < x2)
- x3 += (static_cast<uint64_t>(1) << 32);
- uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF);
- uint64_t hi = x3 + (x1 >> 32);
-
- lo += k;
- if (lo < k)
- hi++;
- *outHigh = hi;
- return lo;
-#endif
- }
-
- static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000
- static const size_t kCapacity = kBitCount / sizeof(Type);
- static const size_t kTypeBit = sizeof(Type) * 8;
-
- Type digits_[kCapacity];
- size_t count_;
-};
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_BIGINTEGER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
-// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
-// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
-
-#ifndef RAPIDJSON_DIYFP_H_
-#define RAPIDJSON_DIYFP_H_
-
-#include "../rapidjson.h"
-
-#if defined(_MSC_VER) && defined(_M_AMD64)
-#include <intrin.h>
-#pragma intrinsic(_BitScanReverse64)
-#pragma intrinsic(_umul128)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-#endif
-
-struct DiyFp {
- DiyFp() : f(), e() {}
-
- DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {}
-
- explicit DiyFp(double d) {
- union {
- double d;
- uint64_t u64;
- } u = { d };
-
- int biased_e = static_cast<int>((u.u64 & kDpExponentMask) >> kDpSignificandSize);
- uint64_t significand = (u.u64 & kDpSignificandMask);
- if (biased_e != 0) {
- f = significand + kDpHiddenBit;
- e = biased_e - kDpExponentBias;
- }
- else {
- f = significand;
- e = kDpMinExponent + 1;
- }
- }
-
- DiyFp operator-(const DiyFp& rhs) const {
- return DiyFp(f - rhs.f, e);
- }
-
- DiyFp operator*(const DiyFp& rhs) const {
-#if defined(_MSC_VER) && defined(_M_AMD64)
- uint64_t h;
- uint64_t l = _umul128(f, rhs.f, &h);
- if (l & (uint64_t(1) << 63)) // rounding
- h++;
- return DiyFp(h, e + rhs.e + 64);
-#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__)
- __extension__ typedef unsigned __int128 uint128;
- uint128 p = static_cast<uint128>(f) * static_cast<uint128>(rhs.f);
- uint64_t h = static_cast<uint64_t>(p >> 64);
- uint64_t l = static_cast<uint64_t>(p);
- if (l & (uint64_t(1) << 63)) // rounding
- h++;
- return DiyFp(h, e + rhs.e + 64);
-#else
- const uint64_t M32 = 0xFFFFFFFF;
- const uint64_t a = f >> 32;
- const uint64_t b = f & M32;
- const uint64_t c = rhs.f >> 32;
- const uint64_t d = rhs.f & M32;
- const uint64_t ac = a * c;
- const uint64_t bc = b * c;
- const uint64_t ad = a * d;
- const uint64_t bd = b * d;
- uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32);
- tmp += 1U << 31; /// mult_round
- return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64);
-#endif
- }
-
- DiyFp Normalize() const {
-#if defined(_MSC_VER) && defined(_M_AMD64)
- unsigned long index;
- _BitScanReverse64(&index, f);
- return DiyFp(f << (63 - index), e - (63 - index));
-#elif defined(__GNUC__) && __GNUC__ >= 4
- int s = __builtin_clzll(f);
- return DiyFp(f << s, e - s);
-#else
- DiyFp res = *this;
- while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
- res.f <<= 1;
- res.e--;
- }
- return res;
-#endif
- }
-
- DiyFp NormalizeBoundary() const {
- DiyFp res = *this;
- while (!(res.f & (kDpHiddenBit << 1))) {
- res.f <<= 1;
- res.e--;
- }
- res.f <<= (kDiySignificandSize - kDpSignificandSize - 2);
- res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2);
- return res;
- }
-
- void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const {
- DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary();
- DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1);
- mi.f <<= mi.e - pl.e;
- mi.e = pl.e;
- *plus = pl;
- *minus = mi;
- }
-
- double ToDouble() const {
- union {
- double d;
- uint64_t u64;
- }u;
- const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
- static_cast<uint64_t>(e + kDpExponentBias);
- u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
- return u.d;
- }
-
- static const int kDiySignificandSize = 64;
- static const int kDpSignificandSize = 52;
- static const int kDpExponentBias = 0x3FF + kDpSignificandSize;
- static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
- static const int kDpMinExponent = -kDpExponentBias;
- static const int kDpDenormalExponent = -kDpExponentBias + 1;
- static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
- static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
- static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
-
- uint64_t f;
- int e;
-};
-
-inline DiyFp GetCachedPowerByIndex(size_t index) {
- // 10^-348, 10^-340, ..., 10^340
- static const uint64_t kCachedPowers_F[] = {
- RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
- RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
- RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
- RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
- RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
- RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
- RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
- RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
- RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
- RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
- RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
- RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
- RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
- RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
- RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
- RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
- RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
- RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
- RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
- RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
- RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
- RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
- RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
- RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
- RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
- RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
- RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
- RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
- RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
- RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
- RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
- RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
- RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
- RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
- RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
- RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
- RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
- RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
- RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
- RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
- RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
- RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
- RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
- RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
- };
- static const int16_t kCachedPowers_E[] = {
- -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
- -954, -927, -901, -874, -847, -821, -794, -768, -741, -715,
- -688, -661, -635, -608, -582, -555, -529, -502, -475, -449,
- -422, -396, -369, -343, -316, -289, -263, -236, -210, -183,
- -157, -130, -103, -77, -50, -24, 3, 30, 56, 83,
- 109, 136, 162, 189, 216, 242, 269, 295, 322, 348,
- 375, 402, 428, 455, 481, 508, 534, 561, 588, 614,
- 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
- 907, 933, 960, 986, 1013, 1039, 1066
- };
- return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
-}
-
-inline DiyFp GetCachedPower(int e, int* K) {
-
- //int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
- double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive
- int k = static_cast<int>(dk);
- if (dk - k > 0.0)
- k++;
-
- unsigned index = static_cast<unsigned>((k >> 3) + 1);
- *K = -(-348 + static_cast<int>(index << 3)); // decimal exponent no need lookup table
-
- return GetCachedPowerByIndex(index);
-}
-
-inline DiyFp GetCachedPower10(int exp, int *outExp) {
- unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
- *outExp = -348 + static_cast<int>(index) * 8;
- return GetCachedPowerByIndex(index);
- }
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-RAPIDJSON_DIAG_OFF(padded)
-#endif
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_DIYFP_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
-// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
-// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
-
-#ifndef RAPIDJSON_DTOA_
-#define RAPIDJSON_DTOA_
-
-#include "itoa.h" // GetDigitsLut()
-#include "diyfp.h"
-#include "ieee754.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
-#endif
-
-inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
- while (rest < wp_w && delta - rest >= ten_kappa &&
- (rest + ten_kappa < wp_w || /// closer
- wp_w - rest > rest + ten_kappa - wp_w)) {
- buffer[len - 1]--;
- rest += ten_kappa;
- }
-}
-
-inline unsigned CountDecimalDigit32(uint32_t n) {
- // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
- if (n < 10) return 1;
- if (n < 100) return 2;
- if (n < 1000) return 3;
- if (n < 10000) return 4;
- if (n < 100000) return 5;
- if (n < 1000000) return 6;
- if (n < 10000000) return 7;
- if (n < 100000000) return 8;
- // Will not reach 10 digits in DigitGen()
- //if (n < 1000000000) return 9;
- //return 10;
- return 9;
-}
-
-inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
- static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
- const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
- const DiyFp wp_w = Mp - W;
- uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
- uint64_t p2 = Mp.f & (one.f - 1);
- unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
- *len = 0;
-
- while (kappa > 0) {
- uint32_t d = 0;
- switch (kappa) {
- case 9: d = p1 / 100000000; p1 %= 100000000; break;
- case 8: d = p1 / 10000000; p1 %= 10000000; break;
- case 7: d = p1 / 1000000; p1 %= 1000000; break;
- case 6: d = p1 / 100000; p1 %= 100000; break;
- case 5: d = p1 / 10000; p1 %= 10000; break;
- case 4: d = p1 / 1000; p1 %= 1000; break;
- case 3: d = p1 / 100; p1 %= 100; break;
- case 2: d = p1 / 10; p1 %= 10; break;
- case 1: d = p1; p1 = 0; break;
- default:;
- }
- if (d || *len)
- buffer[(*len)++] = static_cast<char>('0' + static_cast<char>(d));
- kappa--;
- uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
- if (tmp <= delta) {
- *K += kappa;
- GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
- return;
- }
- }
-
- // kappa = 0
- for (;;) {
- p2 *= 10;
- delta *= 10;
- char d = static_cast<char>(p2 >> -one.e);
- if (d || *len)
- buffer[(*len)++] = static_cast<char>('0' + d);
- p2 &= one.f - 1;
- kappa--;
- if (p2 < delta) {
- *K += kappa;
- int index = -static_cast<int>(kappa);
- GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
- return;
- }
- }
-}
-
-inline void Grisu2(double value, char* buffer, int* length, int* K) {
- const DiyFp v(value);
- DiyFp w_m, w_p;
- v.NormalizedBoundaries(&w_m, &w_p);
-
- const DiyFp c_mk = GetCachedPower(w_p.e, K);
- const DiyFp W = v.Normalize() * c_mk;
- DiyFp Wp = w_p * c_mk;
- DiyFp Wm = w_m * c_mk;
- Wm.f++;
- Wp.f--;
- DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K);
-}
-
-inline char* WriteExponent(int K, char* buffer) {
- if (K < 0) {
- *buffer++ = '-';
- K = -K;
- }
-
- if (K >= 100) {
- *buffer++ = static_cast<char>('0' + static_cast<char>(K / 100));
- K %= 100;
- const char* d = GetDigitsLut() + K * 2;
- *buffer++ = d[0];
- *buffer++ = d[1];
- }
- else if (K >= 10) {
- const char* d = GetDigitsLut() + K * 2;
- *buffer++ = d[0];
- *buffer++ = d[1];
- }
- else
- *buffer++ = static_cast<char>('0' + static_cast<char>(K));
-
- return buffer;
-}
-
-inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
- const int kk = length + k; // 10^(kk-1) <= v < 10^kk
-
- if (0 <= k && kk <= 21) {
- // 1234e7 -> 12340000000
- for (int i = length; i < kk; i++)
- buffer[i] = '0';
- buffer[kk] = '.';
- buffer[kk + 1] = '0';
- return &buffer[kk + 2];
- }
- else if (0 < kk && kk <= 21) {
- // 1234e-2 -> 12.34
- std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
- buffer[kk] = '.';
- if (0 > k + maxDecimalPlaces) {
- // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
- // Remove extra trailing zeros (at least one) after truncation.
- for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
- if (buffer[i] != '0')
- return &buffer[i + 1];
- return &buffer[kk + 2]; // Reserve one zero
- }
- else
- return &buffer[length + 1];
- }
- else if (-6 < kk && kk <= 0) {
- // 1234e-6 -> 0.001234
- const int offset = 2 - kk;
- std::memmove(&buffer[offset], &buffer[0], static_cast<size_t>(length));
- buffer[0] = '0';
- buffer[1] = '.';
- for (int i = 2; i < offset; i++)
- buffer[i] = '0';
- if (length - kk > maxDecimalPlaces) {
- // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
- // Remove extra trailing zeros (at least one) after truncation.
- for (int i = maxDecimalPlaces + 1; i > 2; i--)
- if (buffer[i] != '0')
- return &buffer[i + 1];
- return &buffer[3]; // Reserve one zero
- }
- else
- return &buffer[length + offset];
- }
- else if (kk < -maxDecimalPlaces) {
- // Truncate to zero
- buffer[0] = '0';
- buffer[1] = '.';
- buffer[2] = '0';
- return &buffer[3];
- }
- else if (length == 1) {
- // 1e30
- buffer[1] = 'e';
- return WriteExponent(kk - 1, &buffer[2]);
- }
- else {
- // 1234e30 -> 1.234e33
- std::memmove(&buffer[2], &buffer[1], static_cast<size_t>(length - 1));
- buffer[1] = '.';
- buffer[length + 1] = 'e';
- return WriteExponent(kk - 1, &buffer[0 + length + 2]);
- }
-}
-
-inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
- RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
- Double d(value);
- if (d.IsZero()) {
- if (d.Sign())
- *buffer++ = '-'; // -0.0, Issue #289
- buffer[0] = '0';
- buffer[1] = '.';
- buffer[2] = '0';
- return &buffer[3];
- }
- else {
- if (value < 0) {
- *buffer++ = '-';
- value = -value;
- }
- int length, K;
- Grisu2(value, buffer, &length, &K);
- return Prettify(buffer, length, K, maxDecimalPlaces);
- }
-}
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_DTOA_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_IEEE754_
-#define RAPIDJSON_IEEE754_
-
-#include "../rapidjson.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-class Double {
-public:
- Double() {}
- Double(double d) : d_(d) {}
- Double(uint64_t u) : u_(u) {}
-
- double Value() const { return d_; }
- uint64_t Uint64Value() const { return u_; }
-
- double NextPositiveDouble() const {
- RAPIDJSON_ASSERT(!Sign());
- return Double(u_ + 1).Value();
- }
-
- bool Sign() const { return (u_ & kSignMask) != 0; }
- uint64_t Significand() const { return u_ & kSignificandMask; }
- int Exponent() const { return static_cast<int>(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); }
-
- bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; }
- bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; }
- bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; }
- bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; }
- bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; }
-
- uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); }
- int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
- uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
-
- static unsigned EffectiveSignificandSize(int order) {
- if (order >= -1021)
- return 53;
- else if (order <= -1074)
- return 0;
- else
- return static_cast<unsigned>(order) + 1074;
- }
-
-private:
- static const int kSignificandSize = 52;
- static const int kExponentBias = 0x3FF;
- static const int kDenormalExponent = 1 - kExponentBias;
- static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
- static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
- static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
- static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
-
- union {
- double d_;
- uint64_t u_;
- };
-};
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_IEEE754_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ITOA_
-#define RAPIDJSON_ITOA_
-
-#include "../rapidjson.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-inline const char* GetDigitsLut() {
- static const char cDigitsLut[200] = {
- '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
- '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
- '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
- '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
- '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
- '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
- '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
- '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
- '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
- '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
- };
- return cDigitsLut;
-}
-
-inline char* u32toa(uint32_t value, char* buffer) {
- const char* cDigitsLut = GetDigitsLut();
-
- if (value < 10000) {
- const uint32_t d1 = (value / 100) << 1;
- const uint32_t d2 = (value % 100) << 1;
-
- if (value >= 1000)
- *buffer++ = cDigitsLut[d1];
- if (value >= 100)
- *buffer++ = cDigitsLut[d1 + 1];
- if (value >= 10)
- *buffer++ = cDigitsLut[d2];
- *buffer++ = cDigitsLut[d2 + 1];
- }
- else if (value < 100000000) {
- // value = bbbbcccc
- const uint32_t b = value / 10000;
- const uint32_t c = value % 10000;
-
- const uint32_t d1 = (b / 100) << 1;
- const uint32_t d2 = (b % 100) << 1;
-
- const uint32_t d3 = (c / 100) << 1;
- const uint32_t d4 = (c % 100) << 1;
-
- if (value >= 10000000)
- *buffer++ = cDigitsLut[d1];
- if (value >= 1000000)
- *buffer++ = cDigitsLut[d1 + 1];
- if (value >= 100000)
- *buffer++ = cDigitsLut[d2];
- *buffer++ = cDigitsLut[d2 + 1];
-
- *buffer++ = cDigitsLut[d3];
- *buffer++ = cDigitsLut[d3 + 1];
- *buffer++ = cDigitsLut[d4];
- *buffer++ = cDigitsLut[d4 + 1];
- }
- else {
- // value = aabbbbcccc in decimal
-
- const uint32_t a = value / 100000000; // 1 to 42
- value %= 100000000;
-
- if (a >= 10) {
- const unsigned i = a << 1;
- *buffer++ = cDigitsLut[i];
- *buffer++ = cDigitsLut[i + 1];
- }
- else
- *buffer++ = static_cast<char>('0' + static_cast<char>(a));
-
- const uint32_t b = value / 10000; // 0 to 9999
- const uint32_t c = value % 10000; // 0 to 9999
-
- const uint32_t d1 = (b / 100) << 1;
- const uint32_t d2 = (b % 100) << 1;
-
- const uint32_t d3 = (c / 100) << 1;
- const uint32_t d4 = (c % 100) << 1;
-
- *buffer++ = cDigitsLut[d1];
- *buffer++ = cDigitsLut[d1 + 1];
- *buffer++ = cDigitsLut[d2];
- *buffer++ = cDigitsLut[d2 + 1];
- *buffer++ = cDigitsLut[d3];
- *buffer++ = cDigitsLut[d3 + 1];
- *buffer++ = cDigitsLut[d4];
- *buffer++ = cDigitsLut[d4 + 1];
- }
- return buffer;
-}
-
-inline char* i32toa(int32_t value, char* buffer) {
- uint32_t u = static_cast<uint32_t>(value);
- if (value < 0) {
- *buffer++ = '-';
- u = ~u + 1;
- }
-
- return u32toa(u, buffer);
-}
-
-inline char* u64toa(uint64_t value, char* buffer) {
- const char* cDigitsLut = GetDigitsLut();
- const uint64_t kTen8 = 100000000;
- const uint64_t kTen9 = kTen8 * 10;
- const uint64_t kTen10 = kTen8 * 100;
- const uint64_t kTen11 = kTen8 * 1000;
- const uint64_t kTen12 = kTen8 * 10000;
- const uint64_t kTen13 = kTen8 * 100000;
- const uint64_t kTen14 = kTen8 * 1000000;
- const uint64_t kTen15 = kTen8 * 10000000;
- const uint64_t kTen16 = kTen8 * kTen8;
-
- if (value < kTen8) {
- uint32_t v = static_cast<uint32_t>(value);
- if (v < 10000) {
- const uint32_t d1 = (v / 100) << 1;
- const uint32_t d2 = (v % 100) << 1;
-
- if (v >= 1000)
- *buffer++ = cDigitsLut[d1];
- if (v >= 100)
- *buffer++ = cDigitsLut[d1 + 1];
- if (v >= 10)
- *buffer++ = cDigitsLut[d2];
- *buffer++ = cDigitsLut[d2 + 1];
- }
- else {
- // value = bbbbcccc
- const uint32_t b = v / 10000;
- const uint32_t c = v % 10000;
-
- const uint32_t d1 = (b / 100) << 1;
- const uint32_t d2 = (b % 100) << 1;
-
- const uint32_t d3 = (c / 100) << 1;
- const uint32_t d4 = (c % 100) << 1;
-
- if (value >= 10000000)
- *buffer++ = cDigitsLut[d1];
- if (value >= 1000000)
- *buffer++ = cDigitsLut[d1 + 1];
- if (value >= 100000)
- *buffer++ = cDigitsLut[d2];
- *buffer++ = cDigitsLut[d2 + 1];
-
- *buffer++ = cDigitsLut[d3];
- *buffer++ = cDigitsLut[d3 + 1];
- *buffer++ = cDigitsLut[d4];
- *buffer++ = cDigitsLut[d4 + 1];
- }
- }
- else if (value < kTen16) {
- const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
- const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
-
- const uint32_t b0 = v0 / 10000;
- const uint32_t c0 = v0 % 10000;
-
- const uint32_t d1 = (b0 / 100) << 1;
- const uint32_t d2 = (b0 % 100) << 1;
-
- const uint32_t d3 = (c0 / 100) << 1;
- const uint32_t d4 = (c0 % 100) << 1;
-
- const uint32_t b1 = v1 / 10000;
- const uint32_t c1 = v1 % 10000;
-
- const uint32_t d5 = (b1 / 100) << 1;
- const uint32_t d6 = (b1 % 100) << 1;
-
- const uint32_t d7 = (c1 / 100) << 1;
- const uint32_t d8 = (c1 % 100) << 1;
-
- if (value >= kTen15)
- *buffer++ = cDigitsLut[d1];
- if (value >= kTen14)
- *buffer++ = cDigitsLut[d1 + 1];
- if (value >= kTen13)
- *buffer++ = cDigitsLut[d2];
- if (value >= kTen12)
- *buffer++ = cDigitsLut[d2 + 1];
- if (value >= kTen11)
- *buffer++ = cDigitsLut[d3];
- if (value >= kTen10)
- *buffer++ = cDigitsLut[d3 + 1];
- if (value >= kTen9)
- *buffer++ = cDigitsLut[d4];
- if (value >= kTen8)
- *buffer++ = cDigitsLut[d4 + 1];
-
- *buffer++ = cDigitsLut[d5];
- *buffer++ = cDigitsLut[d5 + 1];
- *buffer++ = cDigitsLut[d6];
- *buffer++ = cDigitsLut[d6 + 1];
- *buffer++ = cDigitsLut[d7];
- *buffer++ = cDigitsLut[d7 + 1];
- *buffer++ = cDigitsLut[d8];
- *buffer++ = cDigitsLut[d8 + 1];
- }
- else {
- const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
- value %= kTen16;
-
- if (a < 10)
- *buffer++ = static_cast<char>('0' + static_cast<char>(a));
- else if (a < 100) {
- const uint32_t i = a << 1;
- *buffer++ = cDigitsLut[i];
- *buffer++ = cDigitsLut[i + 1];
- }
- else if (a < 1000) {
- *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
-
- const uint32_t i = (a % 100) << 1;
- *buffer++ = cDigitsLut[i];
- *buffer++ = cDigitsLut[i + 1];
- }
- else {
- const uint32_t i = (a / 100) << 1;
- const uint32_t j = (a % 100) << 1;
- *buffer++ = cDigitsLut[i];
- *buffer++ = cDigitsLut[i + 1];
- *buffer++ = cDigitsLut[j];
- *buffer++ = cDigitsLut[j + 1];
- }
-
- const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
- const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
-
- const uint32_t b0 = v0 / 10000;
- const uint32_t c0 = v0 % 10000;
-
- const uint32_t d1 = (b0 / 100) << 1;
- const uint32_t d2 = (b0 % 100) << 1;
-
- const uint32_t d3 = (c0 / 100) << 1;
- const uint32_t d4 = (c0 % 100) << 1;
-
- const uint32_t b1 = v1 / 10000;
- const uint32_t c1 = v1 % 10000;
-
- const uint32_t d5 = (b1 / 100) << 1;
- const uint32_t d6 = (b1 % 100) << 1;
-
- const uint32_t d7 = (c1 / 100) << 1;
- const uint32_t d8 = (c1 % 100) << 1;
-
- *buffer++ = cDigitsLut[d1];
- *buffer++ = cDigitsLut[d1 + 1];
- *buffer++ = cDigitsLut[d2];
- *buffer++ = cDigitsLut[d2 + 1];
- *buffer++ = cDigitsLut[d3];
- *buffer++ = cDigitsLut[d3 + 1];
- *buffer++ = cDigitsLut[d4];
- *buffer++ = cDigitsLut[d4 + 1];
- *buffer++ = cDigitsLut[d5];
- *buffer++ = cDigitsLut[d5 + 1];
- *buffer++ = cDigitsLut[d6];
- *buffer++ = cDigitsLut[d6 + 1];
- *buffer++ = cDigitsLut[d7];
- *buffer++ = cDigitsLut[d7 + 1];
- *buffer++ = cDigitsLut[d8];
- *buffer++ = cDigitsLut[d8 + 1];
- }
-
- return buffer;
-}
-
-inline char* i64toa(int64_t value, char* buffer) {
- uint64_t u = static_cast<uint64_t>(value);
- if (value < 0) {
- *buffer++ = '-';
- u = ~u + 1;
- }
-
- return u64toa(u, buffer);
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_ITOA_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_META_H_
-#define RAPIDJSON_INTERNAL_META_H_
-
-#include "../rapidjson.h"
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-#if defined(_MSC_VER)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(6334)
-#endif
-
-#if RAPIDJSON_HAS_CXX11_TYPETRAITS
-#include <type_traits>
-#endif
-
-//@cond RAPIDJSON_INTERNAL
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
-template <typename T> struct Void { typedef void Type; };
-
-///////////////////////////////////////////////////////////////////////////////
-// BoolType, TrueType, FalseType
-//
-template <bool Cond> struct BoolType {
- static const bool Value = Cond;
- typedef BoolType Type;
-};
-typedef BoolType<true> TrueType;
-typedef BoolType<false> FalseType;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
-//
-
-template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
-template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
-template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
-template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
-
-template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
-template <> struct AndExprCond<true, true> : TrueType {};
-template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
-template <> struct OrExprCond<false, false> : FalseType {};
-
-template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
-template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
-template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
-template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// AddConst, MaybeAddConst, RemoveConst
-template <typename T> struct AddConst { typedef const T Type; };
-template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
-template <typename T> struct RemoveConst { typedef T Type; };
-template <typename T> struct RemoveConst<const T> { typedef T Type; };
-
-
-///////////////////////////////////////////////////////////////////////////////
-// IsSame, IsConst, IsMoreConst, IsPointer
-//
-template <typename T, typename U> struct IsSame : FalseType {};
-template <typename T> struct IsSame<T, T> : TrueType {};
-
-template <typename T> struct IsConst : FalseType {};
-template <typename T> struct IsConst<const T> : TrueType {};
-
-template <typename CT, typename T>
-struct IsMoreConst
- : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
- BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
-
-template <typename T> struct IsPointer : FalseType {};
-template <typename T> struct IsPointer<T*> : TrueType {};
-
-///////////////////////////////////////////////////////////////////////////////
-// IsBaseOf
-//
-#if RAPIDJSON_HAS_CXX11_TYPETRAITS
-
-template <typename B, typename D> struct IsBaseOf
- : BoolType< ::std::is_base_of<B,D>::value> {};
-
-#else // simplified version adopted from Boost
-
-template<typename B, typename D> struct IsBaseOfImpl {
- RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
- RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
-
- typedef char (&Yes)[1];
- typedef char (&No) [2];
-
- template <typename T>
- static Yes Check(const D*, T);
- static No Check(const B*, int);
-
- struct Host {
- operator const B*() const;
- operator const D*();
- };
-
- enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
-};
-
-template <typename B, typename D> struct IsBaseOf
- : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
-
-#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
-
-
-//////////////////////////////////////////////////////////////////////////
-// EnableIf / DisableIf
-//
-template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
-template <typename T> struct EnableIfCond<false, T> { /* empty */ };
-
-template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
-template <typename T> struct DisableIfCond<true, T> { /* empty */ };
-
-template <typename Condition, typename T = void>
-struct EnableIf : EnableIfCond<Condition::Value, T> {};
-
-template <typename Condition, typename T = void>
-struct DisableIf : DisableIfCond<Condition::Value, T> {};
-
-// SFINAE helpers
-struct SfinaeTag {};
-template <typename T> struct RemoveSfinaeTag;
-template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
-
-#define RAPIDJSON_REMOVEFPTR_(type) \
- typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
- < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
-
-#define RAPIDJSON_ENABLEIF(cond) \
- typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
- <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
-
-#define RAPIDJSON_DISABLEIF(cond) \
- typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
- <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
-
-#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
- typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
- <RAPIDJSON_REMOVEFPTR_(cond), \
- RAPIDJSON_REMOVEFPTR_(returntype)>::Type
-
-#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
- typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
- <RAPIDJSON_REMOVEFPTR_(cond), \
- RAPIDJSON_REMOVEFPTR_(returntype)>::Type
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-//@endcond
-
-#if defined(__GNUC__) || defined(_MSC_VER)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_INTERNAL_META_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_POW10_
-#define RAPIDJSON_POW10_
-
-#include "../rapidjson.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-//! Computes integer powers of 10 in double (10.0^n).
-/*! This function uses lookup table for fast and accurate results.
- \param n non-negative exponent. Must <= 308.
- \return 10.0^n
-*/
-inline double Pow10(int n) {
- static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
- 1e+0,
- 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
- 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
- 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
- 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
- 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
- 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
- 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
- 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
- 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
- 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
- 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
- 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
- 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
- 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
- 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
- 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
- };
- RAPIDJSON_ASSERT(n >= 0 && n <= 308);
- return e[n];
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_POW10_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_REGEX_H_
-#define RAPIDJSON_INTERNAL_REGEX_H_
-
-#include "../allocators.h"
-#include "../stream.h"
-#include "stack.h"
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-RAPIDJSON_DIAG_OFF(switch-enum)
-RAPIDJSON_DIAG_OFF(implicit-fallthrough)
-#endif
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
-#endif
-
-#ifndef RAPIDJSON_REGEX_VERBOSE
-#define RAPIDJSON_REGEX_VERBOSE 0
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericRegex
-
-static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
-static const SizeType kRegexInvalidRange = ~SizeType(0);
-
-//! Regular expression engine with subset of ECMAscript grammar.
-/*!
- Supported regular expression syntax:
- - \c ab Concatenation
- - \c a|b Alternation
- - \c a? Zero or one
- - \c a* Zero or more
- - \c a+ One or more
- - \c a{3} Exactly 3 times
- - \c a{3,} At least 3 times
- - \c a{3,5} 3 to 5 times
- - \c (ab) Grouping
- - \c ^a At the beginning
- - \c a$ At the end
- - \c . Any character
- - \c [abc] Character classes
- - \c [a-c] Character class range
- - \c [a-z0-9_] Character class combination
- - \c [^abc] Negated character classes
- - \c [^a-c] Negated character class range
- - \c [\b] Backspace (U+0008)
- - \c \\| \\\\ ... Escape characters
- - \c \\f Form feed (U+000C)
- - \c \\n Line feed (U+000A)
- - \c \\r Carriage return (U+000D)
- - \c \\t Tab (U+0009)
- - \c \\v Vertical tab (U+000B)
-
- \note This is a Thompson NFA engine, implemented with reference to
- Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).",
- https://swtch.com/~rsc/regexp/regexp1.html
-*/
-template <typename Encoding, typename Allocator = CrtAllocator>
-class GenericRegex {
-public:
- typedef typename Encoding::Ch Ch;
-
- GenericRegex(const Ch* source, Allocator* allocator = 0) :
- states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
- stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
- {
- GenericStringStream<Encoding> ss(source);
- DecodedStream<GenericStringStream<Encoding> > ds(ss);
- Parse(ds);
- }
-
- ~GenericRegex() {
- Allocator::Free(stateSet_);
- }
-
- bool IsValid() const {
- return root_ != kRegexInvalidState;
- }
-
- template <typename InputStream>
- bool Match(InputStream& is) const {
- return SearchWithAnchoring(is, true, true);
- }
-
- bool Match(const Ch* s) const {
- GenericStringStream<Encoding> is(s);
- return Match(is);
- }
-
- template <typename InputStream>
- bool Search(InputStream& is) const {
- return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
- }
-
- bool Search(const Ch* s) const {
- GenericStringStream<Encoding> is(s);
- return Search(is);
- }
-
-private:
- enum Operator {
- kZeroOrOne,
- kZeroOrMore,
- kOneOrMore,
- kConcatenation,
- kAlternation,
- kLeftParenthesis
- };
-
- static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.'
- static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
- static const unsigned kRangeNegationFlag = 0x80000000;
-
- struct Range {
- unsigned start; //
- unsigned end;
- SizeType next;
- };
-
- struct State {
- SizeType out; //!< Equals to kInvalid for matching state
- SizeType out1; //!< Equals to non-kInvalid for split
- SizeType rangeStart;
- unsigned codepoint;
- };
-
- struct Frag {
- Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
- SizeType start;
- SizeType out; //!< link-list of all output states
- SizeType minIndex;
- };
-
- template <typename SourceStream>
- class DecodedStream {
- public:
- DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
- unsigned Peek() { return codepoint_; }
- unsigned Take() {
- unsigned c = codepoint_;
- if (c) // No further decoding when '\0'
- Decode();
- return c;
- }
-
- private:
- void Decode() {
- if (!Encoding::Decode(ss_, &codepoint_))
- codepoint_ = 0;
- }
-
- SourceStream& ss_;
- unsigned codepoint_;
- };
-
- State& GetState(SizeType index) {
- RAPIDJSON_ASSERT(index < stateCount_);
- return states_.template Bottom<State>()[index];
- }
-
- const State& GetState(SizeType index) const {
- RAPIDJSON_ASSERT(index < stateCount_);
- return states_.template Bottom<State>()[index];
- }
-
- Range& GetRange(SizeType index) {
- RAPIDJSON_ASSERT(index < rangeCount_);
- return ranges_.template Bottom<Range>()[index];
- }
-
- const Range& GetRange(SizeType index) const {
- RAPIDJSON_ASSERT(index < rangeCount_);
- return ranges_.template Bottom<Range>()[index];
- }
-
- template <typename InputStream>
- void Parse(DecodedStream<InputStream>& ds) {
- Allocator allocator;
- Stack<Allocator> operandStack(&allocator, 256); // Frag
- Stack<Allocator> operatorStack(&allocator, 256); // Operator
- Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
-
- *atomCountStack.template Push<unsigned>() = 0;
-
- unsigned codepoint;
- while (ds.Peek() != 0) {
- switch (codepoint = ds.Take()) {
- case '^':
- anchorBegin_ = true;
- break;
-
- case '$':
- anchorEnd_ = true;
- break;
-
- case '|':
- while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
- if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
- return;
- *operatorStack.template Push<Operator>() = kAlternation;
- *atomCountStack.template Top<unsigned>() = 0;
- break;
-
- case '(':
- *operatorStack.template Push<Operator>() = kLeftParenthesis;
- *atomCountStack.template Push<unsigned>() = 0;
- break;
-
- case ')':
- while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
- if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
- return;
- if (operatorStack.Empty())
- return;
- operatorStack.template Pop<Operator>(1);
- atomCountStack.template Pop<unsigned>(1);
- ImplicitConcatenation(atomCountStack, operatorStack);
- break;
-
- case '?':
- if (!Eval(operandStack, kZeroOrOne))
- return;
- break;
-
- case '*':
- if (!Eval(operandStack, kZeroOrMore))
- return;
- break;
-
- case '+':
- if (!Eval(operandStack, kOneOrMore))
- return;
- break;
-
- case '{':
- {
- unsigned n, m;
- if (!ParseUnsigned(ds, &n))
- return;
-
- if (ds.Peek() == ',') {
- ds.Take();
- if (ds.Peek() == '}')
- m = kInfinityQuantifier;
- else if (!ParseUnsigned(ds, &m) || m < n)
- return;
- }
- else
- m = n;
-
- if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
- return;
- ds.Take();
- }
- break;
-
- case '.':
- PushOperand(operandStack, kAnyCharacterClass);
- ImplicitConcatenation(atomCountStack, operatorStack);
- break;
-
- case '[':
- {
- SizeType range;
- if (!ParseRange(ds, &range))
- return;
- SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
- GetState(s).rangeStart = range;
- *operandStack.template Push<Frag>() = Frag(s, s, s);
- }
- ImplicitConcatenation(atomCountStack, operatorStack);
- break;
-
- case '\\': // Escape character
- if (!CharacterEscape(ds, &codepoint))
- return; // Unsupported escape character
- // fall through to default
-
- default: // Pattern character
- PushOperand(operandStack, codepoint);
- ImplicitConcatenation(atomCountStack, operatorStack);
- }
- }
-
- while (!operatorStack.Empty())
- if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
- return;
-
- // Link the operand to matching state.
- if (operandStack.GetSize() == sizeof(Frag)) {
- Frag* e = operandStack.template Pop<Frag>(1);
- Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
- root_ = e->start;
-
-#if RAPIDJSON_REGEX_VERBOSE
- printf("root: %d\n", root_);
- for (SizeType i = 0; i < stateCount_ ; i++) {
- State& s = GetState(i);
- printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
- }
- printf("\n");
-#endif
- }
-
- // Preallocate buffer for SearchWithAnchoring()
- RAPIDJSON_ASSERT(stateSet_ == 0);
- if (stateCount_ > 0) {
- stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
- state0_.template Reserve<SizeType>(stateCount_);
- state1_.template Reserve<SizeType>(stateCount_);
- }
- }
-
- SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
- State* s = states_.template Push<State>();
- s->out = out;
- s->out1 = out1;
- s->codepoint = codepoint;
- s->rangeStart = kRegexInvalidRange;
- return stateCount_++;
- }
-
- void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
- SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
- *operandStack.template Push<Frag>() = Frag(s, s, s);
- }
-
- void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
- if (*atomCountStack.template Top<unsigned>())
- *operatorStack.template Push<Operator>() = kConcatenation;
- (*atomCountStack.template Top<unsigned>())++;
- }
-
- SizeType Append(SizeType l1, SizeType l2) {
- SizeType old = l1;
- while (GetState(l1).out != kRegexInvalidState)
- l1 = GetState(l1).out;
- GetState(l1).out = l2;
- return old;
- }
-
- void Patch(SizeType l, SizeType s) {
- for (SizeType next; l != kRegexInvalidState; l = next) {
- next = GetState(l).out;
- GetState(l).out = s;
- }
- }
-
- bool Eval(Stack<Allocator>& operandStack, Operator op) {
- switch (op) {
- case kConcatenation:
- RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
- {
- Frag e2 = *operandStack.template Pop<Frag>(1);
- Frag e1 = *operandStack.template Pop<Frag>(1);
- Patch(e1.out, e2.start);
- *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
- }
- return true;
-
- case kAlternation:
- if (operandStack.GetSize() >= sizeof(Frag) * 2) {
- Frag e2 = *operandStack.template Pop<Frag>(1);
- Frag e1 = *operandStack.template Pop<Frag>(1);
- SizeType s = NewState(e1.start, e2.start, 0);
- *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
- return true;
- }
- return false;
-
- case kZeroOrOne:
- if (operandStack.GetSize() >= sizeof(Frag)) {
- Frag e = *operandStack.template Pop<Frag>(1);
- SizeType s = NewState(kRegexInvalidState, e.start, 0);
- *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
- return true;
- }
- return false;
-
- case kZeroOrMore:
- if (operandStack.GetSize() >= sizeof(Frag)) {
- Frag e = *operandStack.template Pop<Frag>(1);
- SizeType s = NewState(kRegexInvalidState, e.start, 0);
- Patch(e.out, s);
- *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
- return true;
- }
- return false;
-
- default:
- RAPIDJSON_ASSERT(op == kOneOrMore);
- if (operandStack.GetSize() >= sizeof(Frag)) {
- Frag e = *operandStack.template Pop<Frag>(1);
- SizeType s = NewState(kRegexInvalidState, e.start, 0);
- Patch(e.out, s);
- *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
- return true;
- }
- return false;
- }
- }
-
- bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
- RAPIDJSON_ASSERT(n <= m);
- RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
-
- if (n == 0) {
- if (m == 0) // a{0} not support
- return false;
- else if (m == kInfinityQuantifier)
- Eval(operandStack, kZeroOrMore); // a{0,} -> a*
- else {
- Eval(operandStack, kZeroOrOne); // a{0,5} -> a?
- for (unsigned i = 0; i < m - 1; i++)
- CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a?
- for (unsigned i = 0; i < m - 1; i++)
- Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
- }
- return true;
- }
-
- for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a
- CloneTopOperand(operandStack);
-
- if (m == kInfinityQuantifier)
- Eval(operandStack, kOneOrMore); // a{3,} -> a a a+
- else if (m > n) {
- CloneTopOperand(operandStack); // a{3,5} -> a a a a
- Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a?
- for (unsigned i = n; i < m - 1; i++)
- CloneTopOperand(operandStack); // a{3,5} -> a a a a? a?
- for (unsigned i = n; i < m; i++)
- Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
- }
-
- for (unsigned i = 0; i < n - 1; i++)
- Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
-
- return true;
- }
-
- static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
-
- void CloneTopOperand(Stack<Allocator>& operandStack) {
- const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
- SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
- State* s = states_.template Push<State>(count);
- memcpy(s, &GetState(src.minIndex), count * sizeof(State));
- for (SizeType j = 0; j < count; j++) {
- if (s[j].out != kRegexInvalidState)
- s[j].out += count;
- if (s[j].out1 != kRegexInvalidState)
- s[j].out1 += count;
- }
- *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
- stateCount_ += count;
- }
-
- template <typename InputStream>
- bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
- unsigned r = 0;
- if (ds.Peek() < '0' || ds.Peek() > '9')
- return false;
- while (ds.Peek() >= '0' && ds.Peek() <= '9') {
- if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
- return false; // overflow
- r = r * 10 + (ds.Take() - '0');
- }
- *u = r;
- return true;
- }
-
- template <typename InputStream>
- bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
- bool isBegin = true;
- bool negate = false;
- int step = 0;
- SizeType start = kRegexInvalidRange;
- SizeType current = kRegexInvalidRange;
- unsigned codepoint;
- while ((codepoint = ds.Take()) != 0) {
- if (isBegin) {
- isBegin = false;
- if (codepoint == '^') {
- negate = true;
- continue;
- }
- }
-
- switch (codepoint) {
- case ']':
- if (start == kRegexInvalidRange)
- return false; // Error: nothing inside []
- if (step == 2) { // Add trailing '-'
- SizeType r = NewRange('-');
- RAPIDJSON_ASSERT(current != kRegexInvalidRange);
- GetRange(current).next = r;
- }
- if (negate)
- GetRange(start).start |= kRangeNegationFlag;
- *range = start;
- return true;
-
- case '\\':
- if (ds.Peek() == 'b') {
- ds.Take();
- codepoint = 0x0008; // Escape backspace character
- }
- else if (!CharacterEscape(ds, &codepoint))
- return false;
- // fall through to default
-
- default:
- switch (step) {
- case 1:
- if (codepoint == '-') {
- step++;
- break;
- }
- // fall through to step 0 for other characters
-
- case 0:
- {
- SizeType r = NewRange(codepoint);
- if (current != kRegexInvalidRange)
- GetRange(current).next = r;
- if (start == kRegexInvalidRange)
- start = r;
- current = r;
- }
- step = 1;
- break;
-
- default:
- RAPIDJSON_ASSERT(step == 2);
- GetRange(current).end = codepoint;
- step = 0;
- }
- }
- }
- return false;
- }
-
- SizeType NewRange(unsigned codepoint) {
- Range* r = ranges_.template Push<Range>();
- r->start = r->end = codepoint;
- r->next = kRegexInvalidRange;
- return rangeCount_++;
- }
-
- template <typename InputStream>
- bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
- unsigned codepoint;
- switch (codepoint = ds.Take()) {
- case '^':
- case '$':
- case '|':
- case '(':
- case ')':
- case '?':
- case '*':
- case '+':
- case '.':
- case '[':
- case ']':
- case '{':
- case '}':
- case '\\':
- *escapedCodepoint = codepoint; return true;
- case 'f': *escapedCodepoint = 0x000C; return true;
- case 'n': *escapedCodepoint = 0x000A; return true;
- case 'r': *escapedCodepoint = 0x000D; return true;
- case 't': *escapedCodepoint = 0x0009; return true;
- case 'v': *escapedCodepoint = 0x000B; return true;
- default:
- return false; // Unsupported escape character
- }
- }
-
- template <typename InputStream>
- bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
- RAPIDJSON_ASSERT(IsValid());
- DecodedStream<InputStream> ds(is);
-
- state0_.Clear();
- Stack<Allocator> *current = &state0_, *next = &state1_;
- const size_t stateSetSize = GetStateSetSize();
- std::memset(stateSet_, 0, stateSetSize);
-
- bool matched = AddState(*current, root_);
- unsigned codepoint;
- while (!current->Empty() && (codepoint = ds.Take()) != 0) {
- std::memset(stateSet_, 0, stateSetSize);
- next->Clear();
- matched = false;
- for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
- const State& sr = GetState(*s);
- if (sr.codepoint == codepoint ||
- sr.codepoint == kAnyCharacterClass ||
- (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
- {
- matched = AddState(*next, sr.out) || matched;
- if (!anchorEnd && matched)
- return true;
- }
- if (!anchorBegin)
- AddState(*next, root_);
- }
- internal::Swap(current, next);
- }
-
- return matched;
- }
-
- size_t GetStateSetSize() const {
- return (stateCount_ + 31) / 32 * 4;
- }
-
- // Return whether the added states is a match state
- bool AddState(Stack<Allocator>& l, SizeType index) const {
- RAPIDJSON_ASSERT(index != kRegexInvalidState);
-
- const State& s = GetState(index);
- if (s.out1 != kRegexInvalidState) { // Split
- bool matched = AddState(l, s.out);
- return AddState(l, s.out1) || matched;
- }
- else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
- stateSet_[index >> 5] |= (1 << (index & 31));
- *l.template PushUnsafe<SizeType>() = index;
- }
- return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
- }
-
- bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
- bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
- while (rangeIndex != kRegexInvalidRange) {
- const Range& r = GetRange(rangeIndex);
- if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
- return yes;
- rangeIndex = r.next;
- }
- return !yes;
- }
-
- Stack<Allocator> states_;
- Stack<Allocator> ranges_;
- SizeType root_;
- SizeType stateCount_;
- SizeType rangeCount_;
-
- static const unsigned kInfinityQuantifier = ~0u;
-
- // For SearchWithAnchoring()
- uint32_t* stateSet_; // allocated by states_.GetAllocator()
- mutable Stack<Allocator> state0_;
- mutable Stack<Allocator> state1_;
- bool anchorBegin_;
- bool anchorEnd_;
-};
-
-typedef GenericRegex<UTF8<> > Regex;
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_INTERNAL_REGEX_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_STACK_H_
-#define RAPIDJSON_INTERNAL_STACK_H_
-
-#include "../allocators.h"
-#include "swap.h"
-
-#if defined(__clang__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(c++98-compat)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-///////////////////////////////////////////////////////////////////////////////
-// Stack
-
-//! A type-unsafe stack for storing different types of data.
-/*! \tparam Allocator Allocator for allocating stack memory.
-*/
-template <typename Allocator>
-class Stack {
-public:
- // Optimization note: Do not allocate memory for stack_ in constructor.
- // Do it lazily when first Push() -> Expand() -> Resize().
- Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- Stack(Stack&& rhs)
- : allocator_(rhs.allocator_),
- ownAllocator_(rhs.ownAllocator_),
- stack_(rhs.stack_),
- stackTop_(rhs.stackTop_),
- stackEnd_(rhs.stackEnd_),
- initialCapacity_(rhs.initialCapacity_)
- {
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.stack_ = 0;
- rhs.stackTop_ = 0;
- rhs.stackEnd_ = 0;
- rhs.initialCapacity_ = 0;
- }
-#endif
-
- ~Stack() {
- Destroy();
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- Stack& operator=(Stack&& rhs) {
- if (&rhs != this)
- {
- Destroy();
-
- allocator_ = rhs.allocator_;
- ownAllocator_ = rhs.ownAllocator_;
- stack_ = rhs.stack_;
- stackTop_ = rhs.stackTop_;
- stackEnd_ = rhs.stackEnd_;
- initialCapacity_ = rhs.initialCapacity_;
-
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.stack_ = 0;
- rhs.stackTop_ = 0;
- rhs.stackEnd_ = 0;
- rhs.initialCapacity_ = 0;
- }
- return *this;
- }
-#endif
-
- void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
- internal::Swap(allocator_, rhs.allocator_);
- internal::Swap(ownAllocator_, rhs.ownAllocator_);
- internal::Swap(stack_, rhs.stack_);
- internal::Swap(stackTop_, rhs.stackTop_);
- internal::Swap(stackEnd_, rhs.stackEnd_);
- internal::Swap(initialCapacity_, rhs.initialCapacity_);
- }
-
- void Clear() { stackTop_ = stack_; }
-
- void ShrinkToFit() {
- if (Empty()) {
- // If the stack is empty, completely deallocate the memory.
- Allocator::Free(stack_);
- stack_ = 0;
- stackTop_ = 0;
- stackEnd_ = 0;
- }
- else
- Resize(GetSize());
- }
-
- // Optimization note: try to minimize the size of this function for force inline.
- // Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
- template<typename T>
- RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
- // Expand the stack if needed
- if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
- Expand<T>(count);
- }
-
- template<typename T>
- RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
- Reserve<T>(count);
- return PushUnsafe<T>(count);
- }
-
- template<typename T>
- RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
- RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
- T* ret = reinterpret_cast<T*>(stackTop_);
- stackTop_ += sizeof(T) * count;
- return ret;
- }
-
- template<typename T>
- T* Pop(size_t count) {
- RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
- stackTop_ -= count * sizeof(T);
- return reinterpret_cast<T*>(stackTop_);
- }
-
- template<typename T>
- T* Top() {
- RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
- return reinterpret_cast<T*>(stackTop_ - sizeof(T));
- }
-
- template<typename T>
- const T* Top() const {
- RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
- return reinterpret_cast<T*>(stackTop_ - sizeof(T));
- }
-
- template<typename T>
- T* End() { return reinterpret_cast<T*>(stackTop_); }
-
- template<typename T>
- const T* End() const { return reinterpret_cast<T*>(stackTop_); }
-
- template<typename T>
- T* Bottom() { return reinterpret_cast<T*>(stack_); }
-
- template<typename T>
- const T* Bottom() const { return reinterpret_cast<T*>(stack_); }
-
- bool HasAllocator() const {
- return allocator_ != 0;
- }
-
- Allocator& GetAllocator() {
- RAPIDJSON_ASSERT(allocator_);
- return *allocator_;
- }
-
- bool Empty() const { return stackTop_ == stack_; }
- size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
- size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
-
-private:
- template<typename T>
- void Expand(size_t count) {
- // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
- size_t newCapacity;
- if (stack_ == 0) {
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
- newCapacity = initialCapacity_;
- } else {
- newCapacity = GetCapacity();
- newCapacity += (newCapacity + 1) / 2;
- }
- size_t newSize = GetSize() + sizeof(T) * count;
- if (newCapacity < newSize)
- newCapacity = newSize;
-
- Resize(newCapacity);
- }
-
- void Resize(size_t newCapacity) {
- const size_t size = GetSize(); // Backup the current size
- stack_ = static_cast<char*>(allocator_->Realloc(stack_, GetCapacity(), newCapacity));
- stackTop_ = stack_ + size;
- stackEnd_ = stack_ + newCapacity;
- }
-
- void Destroy() {
- Allocator::Free(stack_);
- RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
- }
-
- // Prohibit copy constructor & assignment operator.
- Stack(const Stack&);
- Stack& operator=(const Stack&);
-
- Allocator* allocator_;
- Allocator* ownAllocator_;
- char *stack_;
- char *stackTop_;
- char *stackEnd_;
- size_t initialCapacity_;
-};
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#if defined(__clang__)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_STACK_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
-#define RAPIDJSON_INTERNAL_STRFUNC_H_
-
-#include "../stream.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-//! Custom strlen() which works on different character types.
-/*! \tparam Ch Character type (e.g. char, wchar_t, short)
- \param s Null-terminated input string.
- \return Number of characters in the string.
- \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
-*/
-template <typename Ch>
-inline SizeType StrLen(const Ch* s) {
- const Ch* p = s;
- while (*p) ++p;
- return SizeType(p - s);
-}
-
-//! Returns number of code points in a encoded string.
-template<typename Encoding>
-bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
- GenericStringStream<Encoding> is(s);
- const typename Encoding::Ch* end = s + length;
- SizeType count = 0;
- while (is.src_ < end) {
- unsigned codepoint;
- if (!Encoding::Decode(is, &codepoint))
- return false;
- count++;
- }
- *outCount = count;
- return true;
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_STRTOD_
-#define RAPIDJSON_STRTOD_
-
-#include "ieee754.h"
-#include "biginteger.h"
-#include "diyfp.h"
-#include "pow10.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-inline double FastPath(double significand, int exp) {
- if (exp < -308)
- return 0.0;
- else if (exp >= 0)
- return significand * internal::Pow10(exp);
- else
- return significand / internal::Pow10(-exp);
-}
-
-inline double StrtodNormalPrecision(double d, int p) {
- if (p < -308) {
- // Prevent expSum < -308, making Pow10(p) = 0
- d = FastPath(d, -308);
- d = FastPath(d, p + 308);
- }
- else
- d = FastPath(d, p);
- return d;
-}
-
-template <typename T>
-inline T Min3(T a, T b, T c) {
- T m = a;
- if (m > b) m = b;
- if (m > c) m = c;
- return m;
-}
-
-inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) {
- const Double db(b);
- const uint64_t bInt = db.IntegerSignificand();
- const int bExp = db.IntegerExponent();
- const int hExp = bExp - 1;
-
- int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0;
-
- // Adjust for decimal exponent
- if (dExp >= 0) {
- dS_Exp2 += dExp;
- dS_Exp5 += dExp;
- }
- else {
- bS_Exp2 -= dExp;
- bS_Exp5 -= dExp;
- hS_Exp2 -= dExp;
- hS_Exp5 -= dExp;
- }
-
- // Adjust for binary exponent
- if (bExp >= 0)
- bS_Exp2 += bExp;
- else {
- dS_Exp2 -= bExp;
- hS_Exp2 -= bExp;
- }
-
- // Adjust for half ulp exponent
- if (hExp >= 0)
- hS_Exp2 += hExp;
- else {
- dS_Exp2 -= hExp;
- bS_Exp2 -= hExp;
- }
-
- // Remove common power of two factor from all three scaled values
- int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2);
- dS_Exp2 -= common_Exp2;
- bS_Exp2 -= common_Exp2;
- hS_Exp2 -= common_Exp2;
-
- BigInteger dS = d;
- dS.MultiplyPow5(static_cast<unsigned>(dS_Exp5)) <<= static_cast<unsigned>(dS_Exp2);
-
- BigInteger bS(bInt);
- bS.MultiplyPow5(static_cast<unsigned>(bS_Exp5)) <<= static_cast<unsigned>(bS_Exp2);
-
- BigInteger hS(1);
- hS.MultiplyPow5(static_cast<unsigned>(hS_Exp5)) <<= static_cast<unsigned>(hS_Exp2);
-
- BigInteger delta(0);
- dS.Difference(bS, &delta);
-
- return delta.Compare(hS);
-}
-
-inline bool StrtodFast(double d, int p, double* result) {
- // Use fast path for string-to-double conversion if possible
- // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/
- if (p > 22 && p < 22 + 16) {
- // Fast Path Cases In Disguise
- d *= internal::Pow10(p - 22);
- p = 22;
- }
-
- if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1
- *result = FastPath(d, p);
- return true;
- }
- else
- return false;
-}
-
-// Compute an approximation and see if it is within 1/2 ULP
-inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
- uint64_t significand = 0;
- size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
- for (; i < length; i++) {
- if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
- (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
- break;
- significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
- }
-
- if (i < length && decimals[i] >= '5') // Rounding
- significand++;
-
- size_t remaining = length - i;
- const unsigned kUlpShift = 3;
- const unsigned kUlp = 1 << kUlpShift;
- int64_t error = (remaining == 0) ? 0 : kUlp / 2;
-
- DiyFp v(significand, 0);
- v = v.Normalize();
- error <<= -v.e;
-
- const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
-
- int actualExp;
- DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
- if (actualExp != dExp) {
- static const DiyFp kPow10[] = {
- DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
- DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
- DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
- DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
- DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
- DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
- DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
- };
- int adjustment = dExp - actualExp - 1;
- RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
- v = v * kPow10[adjustment];
- if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
- error += kUlp / 2;
- }
-
- v = v * cachedPower;
-
- error += kUlp + (error == 0 ? 0 : 1);
-
- const int oldExp = v.e;
- v = v.Normalize();
- error <<= oldExp - v.e;
-
- const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
- unsigned precisionSize = 64 - effectiveSignificandSize;
- if (precisionSize + kUlpShift >= 64) {
- unsigned scaleExp = (precisionSize + kUlpShift) - 63;
- v.f >>= scaleExp;
- v.e += scaleExp;
- error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
- precisionSize -= scaleExp;
- }
-
- DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
- const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
- const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
- if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
- rounded.f++;
- if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340)
- rounded.f >>= 1;
- rounded.e++;
- }
- }
-
- *result = rounded.ToDouble();
-
- return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
-}
-
-inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
- const BigInteger dInt(decimals, length);
- const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
- Double a(approx);
- int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
- if (cmp < 0)
- return a.Value(); // within half ULP
- else if (cmp == 0) {
- // Round towards even
- if (a.Significand() & 1)
- return a.NextPositiveDouble();
- else
- return a.Value();
- }
- else // adjustment
- return a.NextPositiveDouble();
-}
-
-inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
- RAPIDJSON_ASSERT(d >= 0.0);
- RAPIDJSON_ASSERT(length >= 1);
-
- double result;
- if (StrtodFast(d, p, &result))
- return result;
-
- // Trim leading zeros
- while (*decimals == '0' && length > 1) {
- length--;
- decimals++;
- decimalPosition--;
- }
-
- // Trim trailing zeros
- while (decimals[length - 1] == '0' && length > 1) {
- length--;
- decimalPosition--;
- exp++;
- }
-
- // Trim right-most digits
- const int kMaxDecimalDigit = 780;
- if (static_cast<int>(length) > kMaxDecimalDigit) {
- int delta = (static_cast<int>(length) - kMaxDecimalDigit);
- exp += delta;
- decimalPosition -= static_cast<unsigned>(delta);
- length = kMaxDecimalDigit;
- }
-
- // If too small, underflow to zero
- if (int(length) + exp < -324)
- return 0.0;
-
- if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
- return result;
-
- // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
- return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_STRTOD_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_SWAP_H_
-#define RAPIDJSON_INTERNAL_SWAP_H_
-
-#include "../rapidjson.h"
-
-#if defined(__clang__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(c++98-compat)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-//! Custom swap() to avoid dependency on C++ <algorithm> header
-/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
- \note This has the same semantics as std::swap().
-*/
-template <typename T>
-inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
- T tmp = a;
- a = b;
- b = tmp;
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#if defined(__clang__)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_INTERNAL_SWAP_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
-#define RAPIDJSON_ISTREAMWRAPPER_H_
-
-#include "stream.h"
-#include <iosfwd>
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
-/*!
- The classes can be wrapped including but not limited to:
-
- - \c std::istringstream
- - \c std::stringstream
- - \c std::wistringstream
- - \c std::wstringstream
- - \c std::ifstream
- - \c std::fstream
- - \c std::wifstream
- - \c std::wfstream
-
- \tparam StreamType Class derived from \c std::basic_istream.
-*/
-
-template <typename StreamType>
-class BasicIStreamWrapper {
-public:
- typedef typename StreamType::char_type Ch;
- BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
-
- Ch Peek() const {
- typename StreamType::int_type c = stream_.peek();
- return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
- }
-
- Ch Take() {
- typename StreamType::int_type c = stream_.get();
- if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
- count_++;
- return static_cast<Ch>(c);
- }
- else
- return '\0';
- }
-
- // tellg() may return -1 when failed. So we count by ourself.
- size_t Tell() const { return count_; }
-
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- void Put(Ch) { RAPIDJSON_ASSERT(false); }
- void Flush() { RAPIDJSON_ASSERT(false); }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
- // For encoding detection only.
- const Ch* Peek4() const {
- RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
- int i;
- bool hasError = false;
- for (i = 0; i < 4; ++i) {
- typename StreamType::int_type c = stream_.get();
- if (c == StreamType::traits_type::eof()) {
- hasError = true;
- stream_.clear();
- break;
- }
- peekBuffer_[i] = static_cast<Ch>(c);
- }
- for (--i; i >= 0; --i)
- stream_.putback(peekBuffer_[i]);
- return !hasError ? peekBuffer_ : 0;
- }
-
-private:
- BasicIStreamWrapper(const BasicIStreamWrapper&);
- BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
-
- StreamType& stream_;
- size_t count_; //!< Number of characters read. Note:
- mutable Ch peekBuffer_[4];
-};
-
-typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
-typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
-
-#if defined(__clang__) || defined(_MSC_VER)
-RAPIDJSON_DIAG_POP
-#endif
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_ISTREAMWRAPPER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_MEMORYBUFFER_H_
-#define RAPIDJSON_MEMORYBUFFER_H_
-
-#include "stream.h"
-#include "internal/stack.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Represents an in-memory output byte stream.
-/*!
- This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream.
-
- It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file.
-
- Differences between MemoryBuffer and StringBuffer:
- 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer.
- 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator.
-
- \tparam Allocator type for allocating memory buffer.
- \note implements Stream concept
-*/
-template <typename Allocator = CrtAllocator>
-struct GenericMemoryBuffer {
- typedef char Ch; // byte
-
- GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
-
- void Put(Ch c) { *stack_.template Push<Ch>() = c; }
- void Flush() {}
-
- void Clear() { stack_.Clear(); }
- void ShrinkToFit() { stack_.ShrinkToFit(); }
- Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
- void Pop(size_t count) { stack_.template Pop<Ch>(count); }
-
- const Ch* GetBuffer() const {
- return stack_.template Bottom<Ch>();
- }
-
- size_t GetSize() const { return stack_.GetSize(); }
-
- static const size_t kDefaultCapacity = 256;
- mutable internal::Stack<Allocator> stack_;
-};
-
-typedef GenericMemoryBuffer<> MemoryBuffer;
-
-//! Implement specialized version of PutN() with memset() for better performance.
-template<>
-inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
- std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_MEMORYBUFFER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_MEMORYSTREAM_H_
-#define RAPIDJSON_MEMORYSTREAM_H_
-
-#include "stream.h"
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(unreachable-code)
-RAPIDJSON_DIAG_OFF(missing-noreturn)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Represents an in-memory input byte stream.
-/*!
- This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream.
-
- It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file.
-
- Differences between MemoryStream and StringStream:
- 1. StringStream has encoding but MemoryStream is a byte stream.
- 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source.
- 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4().
- \note implements Stream concept
-*/
-struct MemoryStream {
- typedef char Ch; // byte
-
- MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
-
- Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
- Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
- size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
-
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- void Put(Ch) { RAPIDJSON_ASSERT(false); }
- void Flush() { RAPIDJSON_ASSERT(false); }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
- // For encoding detection only.
- const Ch* Peek4() const {
- return Tell() + 4 <= size_ ? src_ : 0;
- }
-
- const Ch* src_; //!< Current read position.
- const Ch* begin_; //!< Original head of the string.
- const Ch* end_; //!< End of stream.
- size_t size_; //!< Size of the stream.
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_MEMORYBUFFER_H_
+++ /dev/null
-// ISO C9x compliant inttypes.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2013 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the product nor the names of its contributors may
-// be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-// The above software in this distribution may have been modified by
-// THL A29 Limited ("Tencent Modifications").
-// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_INTTYPES_H_ // [
-#define _MSC_INTTYPES_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include "stdint.h"
-
-// miloyip: VC supports inttypes.h since VC2013
-#if _MSC_VER >= 1800
-#include <inttypes.h>
-#else
-
-// 7.8 Format conversion of integer types
-
-typedef struct {
- intmax_t quot;
- intmax_t rem;
-} imaxdiv_t;
-
-// 7.8.1 Macros for format specifiers
-
-#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
-
-// The fprintf macros for signed integers are:
-#define PRId8 "d"
-#define PRIi8 "i"
-#define PRIdLEAST8 "d"
-#define PRIiLEAST8 "i"
-#define PRIdFAST8 "d"
-#define PRIiFAST8 "i"
-
-#define PRId16 "hd"
-#define PRIi16 "hi"
-#define PRIdLEAST16 "hd"
-#define PRIiLEAST16 "hi"
-#define PRIdFAST16 "hd"
-#define PRIiFAST16 "hi"
-
-#define PRId32 "I32d"
-#define PRIi32 "I32i"
-#define PRIdLEAST32 "I32d"
-#define PRIiLEAST32 "I32i"
-#define PRIdFAST32 "I32d"
-#define PRIiFAST32 "I32i"
-
-#define PRId64 "I64d"
-#define PRIi64 "I64i"
-#define PRIdLEAST64 "I64d"
-#define PRIiLEAST64 "I64i"
-#define PRIdFAST64 "I64d"
-#define PRIiFAST64 "I64i"
-
-#define PRIdMAX "I64d"
-#define PRIiMAX "I64i"
-
-#define PRIdPTR "Id"
-#define PRIiPTR "Ii"
-
-// The fprintf macros for unsigned integers are:
-#define PRIo8 "o"
-#define PRIu8 "u"
-#define PRIx8 "x"
-#define PRIX8 "X"
-#define PRIoLEAST8 "o"
-#define PRIuLEAST8 "u"
-#define PRIxLEAST8 "x"
-#define PRIXLEAST8 "X"
-#define PRIoFAST8 "o"
-#define PRIuFAST8 "u"
-#define PRIxFAST8 "x"
-#define PRIXFAST8 "X"
-
-#define PRIo16 "ho"
-#define PRIu16 "hu"
-#define PRIx16 "hx"
-#define PRIX16 "hX"
-#define PRIoLEAST16 "ho"
-#define PRIuLEAST16 "hu"
-#define PRIxLEAST16 "hx"
-#define PRIXLEAST16 "hX"
-#define PRIoFAST16 "ho"
-#define PRIuFAST16 "hu"
-#define PRIxFAST16 "hx"
-#define PRIXFAST16 "hX"
-
-#define PRIo32 "I32o"
-#define PRIu32 "I32u"
-#define PRIx32 "I32x"
-#define PRIX32 "I32X"
-#define PRIoLEAST32 "I32o"
-#define PRIuLEAST32 "I32u"
-#define PRIxLEAST32 "I32x"
-#define PRIXLEAST32 "I32X"
-#define PRIoFAST32 "I32o"
-#define PRIuFAST32 "I32u"
-#define PRIxFAST32 "I32x"
-#define PRIXFAST32 "I32X"
-
-#define PRIo64 "I64o"
-#define PRIu64 "I64u"
-#define PRIx64 "I64x"
-#define PRIX64 "I64X"
-#define PRIoLEAST64 "I64o"
-#define PRIuLEAST64 "I64u"
-#define PRIxLEAST64 "I64x"
-#define PRIXLEAST64 "I64X"
-#define PRIoFAST64 "I64o"
-#define PRIuFAST64 "I64u"
-#define PRIxFAST64 "I64x"
-#define PRIXFAST64 "I64X"
-
-#define PRIoMAX "I64o"
-#define PRIuMAX "I64u"
-#define PRIxMAX "I64x"
-#define PRIXMAX "I64X"
-
-#define PRIoPTR "Io"
-#define PRIuPTR "Iu"
-#define PRIxPTR "Ix"
-#define PRIXPTR "IX"
-
-// The fscanf macros for signed integers are:
-#define SCNd8 "d"
-#define SCNi8 "i"
-#define SCNdLEAST8 "d"
-#define SCNiLEAST8 "i"
-#define SCNdFAST8 "d"
-#define SCNiFAST8 "i"
-
-#define SCNd16 "hd"
-#define SCNi16 "hi"
-#define SCNdLEAST16 "hd"
-#define SCNiLEAST16 "hi"
-#define SCNdFAST16 "hd"
-#define SCNiFAST16 "hi"
-
-#define SCNd32 "ld"
-#define SCNi32 "li"
-#define SCNdLEAST32 "ld"
-#define SCNiLEAST32 "li"
-#define SCNdFAST32 "ld"
-#define SCNiFAST32 "li"
-
-#define SCNd64 "I64d"
-#define SCNi64 "I64i"
-#define SCNdLEAST64 "I64d"
-#define SCNiLEAST64 "I64i"
-#define SCNdFAST64 "I64d"
-#define SCNiFAST64 "I64i"
-
-#define SCNdMAX "I64d"
-#define SCNiMAX "I64i"
-
-#ifdef _WIN64 // [
-# define SCNdPTR "I64d"
-# define SCNiPTR "I64i"
-#else // _WIN64 ][
-# define SCNdPTR "ld"
-# define SCNiPTR "li"
-#endif // _WIN64 ]
-
-// The fscanf macros for unsigned integers are:
-#define SCNo8 "o"
-#define SCNu8 "u"
-#define SCNx8 "x"
-#define SCNX8 "X"
-#define SCNoLEAST8 "o"
-#define SCNuLEAST8 "u"
-#define SCNxLEAST8 "x"
-#define SCNXLEAST8 "X"
-#define SCNoFAST8 "o"
-#define SCNuFAST8 "u"
-#define SCNxFAST8 "x"
-#define SCNXFAST8 "X"
-
-#define SCNo16 "ho"
-#define SCNu16 "hu"
-#define SCNx16 "hx"
-#define SCNX16 "hX"
-#define SCNoLEAST16 "ho"
-#define SCNuLEAST16 "hu"
-#define SCNxLEAST16 "hx"
-#define SCNXLEAST16 "hX"
-#define SCNoFAST16 "ho"
-#define SCNuFAST16 "hu"
-#define SCNxFAST16 "hx"
-#define SCNXFAST16 "hX"
-
-#define SCNo32 "lo"
-#define SCNu32 "lu"
-#define SCNx32 "lx"
-#define SCNX32 "lX"
-#define SCNoLEAST32 "lo"
-#define SCNuLEAST32 "lu"
-#define SCNxLEAST32 "lx"
-#define SCNXLEAST32 "lX"
-#define SCNoFAST32 "lo"
-#define SCNuFAST32 "lu"
-#define SCNxFAST32 "lx"
-#define SCNXFAST32 "lX"
-
-#define SCNo64 "I64o"
-#define SCNu64 "I64u"
-#define SCNx64 "I64x"
-#define SCNX64 "I64X"
-#define SCNoLEAST64 "I64o"
-#define SCNuLEAST64 "I64u"
-#define SCNxLEAST64 "I64x"
-#define SCNXLEAST64 "I64X"
-#define SCNoFAST64 "I64o"
-#define SCNuFAST64 "I64u"
-#define SCNxFAST64 "I64x"
-#define SCNXFAST64 "I64X"
-
-#define SCNoMAX "I64o"
-#define SCNuMAX "I64u"
-#define SCNxMAX "I64x"
-#define SCNXMAX "I64X"
-
-#ifdef _WIN64 // [
-# define SCNoPTR "I64o"
-# define SCNuPTR "I64u"
-# define SCNxPTR "I64x"
-# define SCNXPTR "I64X"
-#else // _WIN64 ][
-# define SCNoPTR "lo"
-# define SCNuPTR "lu"
-# define SCNxPTR "lx"
-# define SCNXPTR "lX"
-#endif // _WIN64 ]
-
-#endif // __STDC_FORMAT_MACROS ]
-
-// 7.8.2 Functions for greatest-width integer types
-
-// 7.8.2.1 The imaxabs function
-#define imaxabs _abs64
-
-// 7.8.2.2 The imaxdiv function
-
-// This is modified version of div() function from Microsoft's div.c found
-// in %MSVC.NET%\crt\src\div.c
-#ifdef STATIC_IMAXDIV // [
-static
-#else // STATIC_IMAXDIV ][
-_inline
-#endif // STATIC_IMAXDIV ]
-imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
-{
- imaxdiv_t result;
-
- result.quot = numer / denom;
- result.rem = numer % denom;
-
- if (numer < 0 && result.rem > 0) {
- // did division wrong; must fix up
- ++result.quot;
- result.rem -= denom;
- }
-
- return result;
-}
-
-// 7.8.2.3 The strtoimax and strtoumax functions
-#define strtoimax _strtoi64
-#define strtoumax _strtoui64
-
-// 7.8.2.4 The wcstoimax and wcstoumax functions
-#define wcstoimax _wcstoi64
-#define wcstoumax _wcstoui64
-
-#endif // _MSC_VER >= 1800
-
-#endif // _MSC_INTTYPES_H_ ]
+++ /dev/null
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006-2013 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the product nor the names of its contributors may
-// be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-// The above software in this distribution may have been modified by
-// THL A29 Limited ("Tencent Modifications").
-// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
-#if _MSC_VER >= 1600 // [
-#include <stdint.h>
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-#undef INT8_C
-#undef INT16_C
-#undef INT32_C
-#undef INT64_C
-#undef UINT8_C
-#undef UINT16_C
-#undef UINT32_C
-#undef UINT64_C
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
-// Check out Issue 9 for the details.
-#ifndef INTMAX_C // [
-# define INTMAX_C INT64_C
-#endif // INTMAX_C ]
-#ifndef UINTMAX_C // [
-# define UINTMAX_C UINT64_C
-#endif // UINTMAX_C ]
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-#else // ] _MSC_VER >= 1700 [
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
-// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler would give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#if defined(__cplusplus) && !defined(_M_ARM)
-extern "C" {
-#endif
-# include <wchar.h>
-#if defined(__cplusplus) && !defined(_M_ARM)
-}
-#endif
-
-// Define _W64 macros to mark types changing their size, like intptr_t.
-#ifndef _W64
-# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
-# define _W64 __w64
-# else
-# define _W64
-# endif
-#endif
-
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-
-// Visual Studio 6 and Embedded Visual C++ 4 doesn't
-// realize that, e.g. char has the same size as __int8
-// so we give up on __intX for them.
-#if (_MSC_VER < 1300)
- typedef signed char int8_t;
- typedef signed short int16_t;
- typedef signed int int32_t;
- typedef unsigned char uint8_t;
- typedef unsigned short uint16_t;
- typedef unsigned int uint32_t;
-#else
- typedef signed __int8 int8_t;
- typedef signed __int16 int16_t;
- typedef signed __int32 int32_t;
- typedef unsigned __int8 uint8_t;
- typedef unsigned __int16 uint16_t;
- typedef unsigned __int32 uint32_t;
-#endif
-typedef signed __int64 int64_t;
-typedef unsigned __int64 uint64_t;
-
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
- typedef signed __int64 intptr_t;
- typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
- typedef _W64 signed int intptr_t;
- typedef _W64 unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
-
-#define WINT_MIN 0
-#define WINT_MAX _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
-// Check out Issue 9 for the details.
-#ifndef INTMAX_C // [
-# define INTMAX_C INT64_C
-#endif // INTMAX_C ]
-#ifndef UINTMAX_C // [
-# define UINTMAX_C UINT64_C
-#endif // UINTMAX_C ]
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-#endif // _MSC_VER >= 1600 ]
-
-#endif // _MSC_STDINT_H_ ]
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
-#define RAPIDJSON_OSTREAMWRAPPER_H_
-
-#include "stream.h"
-#include <iosfwd>
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
-/*!
- The classes can be wrapped including but not limited to:
-
- - \c std::ostringstream
- - \c std::stringstream
- - \c std::wpstringstream
- - \c std::wstringstream
- - \c std::ifstream
- - \c std::fstream
- - \c std::wofstream
- - \c std::wfstream
-
- \tparam StreamType Class derived from \c std::basic_ostream.
-*/
-
-template <typename StreamType>
-class BasicOStreamWrapper {
-public:
- typedef typename StreamType::char_type Ch;
- BasicOStreamWrapper(StreamType& stream) : stream_(stream) {}
-
- void Put(Ch c) {
- stream_.put(c);
- }
-
- void Flush() {
- stream_.flush();
- }
-
- // Not implemented
- char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
- char Take() { RAPIDJSON_ASSERT(false); return 0; }
- size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
- char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
-
-private:
- BasicOStreamWrapper(const BasicOStreamWrapper&);
- BasicOStreamWrapper& operator=(const BasicOStreamWrapper&);
-
- StreamType& stream_;
-};
-
-typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
-typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_OSTREAMWRAPPER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_POINTER_H_
-#define RAPIDJSON_POINTER_H_
-
-#include "document.h"
-#include "internal/itoa.h"
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(switch-enum)
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
-
-//! Error code of parsing.
-/*! \ingroup RAPIDJSON_ERRORS
- \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
-*/
-enum PointerParseErrorCode {
- kPointerParseErrorNone = 0, //!< The parse is successful
-
- kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/'
- kPointerParseErrorInvalidEscape, //!< Invalid escape
- kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment
- kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericPointer
-
-//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
-/*!
- This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer"
- (https://tools.ietf.org/html/rfc6901).
-
- A JSON pointer is for identifying a specific value in a JSON document
- (GenericDocument). It can simplify coding of DOM tree manipulation, because it
- can access multiple-level depth of DOM tree with single API call.
-
- After it parses a string representation (e.g. "/foo/0" or URI fragment
- representation (e.g. "#/foo/0") into its internal representation (tokens),
- it can be used to resolve a specific value in multiple documents, or sub-tree
- of documents.
-
- Contrary to GenericValue, Pointer can be copy constructed and copy assigned.
- Apart from assignment, a Pointer cannot be modified after construction.
-
- Although Pointer is very convenient, please aware that constructing Pointer
- involves parsing and dynamic memory allocation. A special constructor with user-
- supplied tokens eliminates these.
-
- GenericPointer depends on GenericDocument and GenericValue.
-
- \tparam ValueType The value type of the DOM tree. E.g. GenericValue<UTF8<> >
- \tparam Allocator The allocator type for allocating memory for internal representation.
-
- \note GenericPointer uses same encoding of ValueType.
- However, Allocator of GenericPointer is independent of Allocator of Value.
-*/
-template <typename ValueType, typename Allocator = CrtAllocator>
-class GenericPointer {
-public:
- typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
- typedef typename ValueType::Ch Ch; //!< Character type from Value
-
- //! A token is the basic units of internal representation.
- /*!
- A JSON pointer string representation "/foo/123" is parsed to two tokens:
- "foo" and 123. 123 will be represented in both numeric form and string form.
- They are resolved according to the actual value type (object or array).
-
- For token that are not numbers, or the numeric value is out of bound
- (greater than limits of SizeType), they are only treated as string form
- (i.e. the token's index will be equal to kPointerInvalidIndex).
-
- This struct is public so that user can create a Pointer without parsing and
- allocation, using a special constructor.
- */
- struct Token {
- const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character.
- SizeType length; //!< Length of the name.
- SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex.
- };
-
- //!@name Constructors and destructor.
- //@{
-
- //! Default constructor.
- GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
-
- //! Constructor that parses a string or URI fragment representation.
- /*!
- \param source A null-terminated, string or URI fragment representation of JSON pointer.
- \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
- */
- explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
- Parse(source, internal::StrLen(source));
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Constructor that parses a string or URI fragment representation.
- /*!
- \param source A string or URI fragment representation of JSON pointer.
- \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
- \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
- Parse(source.c_str(), source.size());
- }
-#endif
-
- //! Constructor that parses a string or URI fragment representation, with length of the source string.
- /*!
- \param source A string or URI fragment representation of JSON pointer.
- \param length Length of source.
- \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
- \note Slightly faster than the overload without length.
- */
- GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
- Parse(source, length);
- }
-
- //! Constructor with user-supplied tokens.
- /*!
- This constructor let user supplies const array of tokens.
- This prevents the parsing process and eliminates allocation.
- This is preferred for memory constrained environments.
-
- \param tokens An constant array of tokens representing the JSON pointer.
- \param tokenCount Number of tokens.
-
- \b Example
- \code
- #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex }
- #define INDEX(i) { #i, sizeof(#i) - 1, i }
-
- static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) };
- static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
- // Equivalent to static const Pointer p("/foo/123");
-
- #undef NAME
- #undef INDEX
- \endcode
- */
- GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
-
- //! Copy constructor.
- GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
- *this = rhs;
- }
-
- //! Destructor.
- ~GenericPointer() {
- if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
- Allocator::Free(tokens_);
- RAPIDJSON_DELETE(ownAllocator_);
- }
-
- //! Assignment operator.
- GenericPointer& operator=(const GenericPointer& rhs) {
- if (this != &rhs) {
- // Do not delete ownAllcator
- if (nameBuffer_)
- Allocator::Free(tokens_);
-
- tokenCount_ = rhs.tokenCount_;
- parseErrorOffset_ = rhs.parseErrorOffset_;
- parseErrorCode_ = rhs.parseErrorCode_;
-
- if (rhs.nameBuffer_)
- CopyFromRaw(rhs); // Normally parsed tokens.
- else {
- tokens_ = rhs.tokens_; // User supplied const tokens.
- nameBuffer_ = 0;
- }
- }
- return *this;
- }
-
- //@}
-
- //!@name Append token
- //@{
-
- //! Append a token and return a new Pointer
- /*!
- \param token Token to be appended.
- \param allocator Allocator for the newly return Pointer.
- \return A new Pointer with appended token.
- */
- GenericPointer Append(const Token& token, Allocator* allocator = 0) const {
- GenericPointer r;
- r.allocator_ = allocator;
- Ch *p = r.CopyFromRaw(*this, 1, token.length + 1);
- std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch));
- r.tokens_[tokenCount_].name = p;
- r.tokens_[tokenCount_].length = token.length;
- r.tokens_[tokenCount_].index = token.index;
- return r;
- }
-
- //! Append a name token with length, and return a new Pointer
- /*!
- \param name Name to be appended.
- \param length Length of name.
- \param allocator Allocator for the newly return Pointer.
- \return A new Pointer with appended token.
- */
- GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const {
- Token token = { name, length, kPointerInvalidIndex };
- return Append(token, allocator);
- }
-
- //! Append a name token without length, and return a new Pointer
- /*!
- \param name Name (const Ch*) to be appended.
- \param allocator Allocator for the newly return Pointer.
- \return A new Pointer with appended token.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
- Append(T* name, Allocator* allocator = 0) const {
- return Append(name, StrLen(name), allocator);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Append a name token, and return a new Pointer
- /*!
- \param name Name to be appended.
- \param allocator Allocator for the newly return Pointer.
- \return A new Pointer with appended token.
- */
- GenericPointer Append(const std::basic_string<Ch>& name, Allocator* allocator = 0) const {
- return Append(name.c_str(), static_cast<SizeType>(name.size()), allocator);
- }
-#endif
-
- //! Append a index token, and return a new Pointer
- /*!
- \param index Index to be appended.
- \param allocator Allocator for the newly return Pointer.
- \return A new Pointer with appended token.
- */
- GenericPointer Append(SizeType index, Allocator* allocator = 0) const {
- char buffer[21];
- char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer);
- SizeType length = static_cast<SizeType>(end - buffer);
- buffer[length] = '\0';
-
- if (sizeof(Ch) == 1) {
- Token token = { reinterpret_cast<Ch*>(buffer), length, index };
- return Append(token, allocator);
- }
- else {
- Ch name[21];
- for (size_t i = 0; i <= length; i++)
- name[i] = buffer[i];
- Token token = { name, length, index };
- return Append(token, allocator);
- }
- }
-
- //! Append a token by value, and return a new Pointer
- /*!
- \param token token to be appended.
- \param allocator Allocator for the newly return Pointer.
- \return A new Pointer with appended token.
- */
- GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const {
- if (token.IsString())
- return Append(token.GetString(), token.GetStringLength(), allocator);
- else {
- RAPIDJSON_ASSERT(token.IsUint64());
- RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
- return Append(static_cast<SizeType>(token.GetUint64()), allocator);
- }
- }
-
- //!@name Handling Parse Error
- //@{
-
- //! Check whether this is a valid pointer.
- bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; }
-
- //! Get the parsing error offset in code unit.
- size_t GetParseErrorOffset() const { return parseErrorOffset_; }
-
- //! Get the parsing error code.
- PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; }
-
- //@}
-
- //! Get the allocator of this pointer.
- Allocator& GetAllocator() { return *allocator_; }
-
- //!@name Tokens
- //@{
-
- //! Get the token array (const version only).
- const Token* GetTokens() const { return tokens_; }
-
- //! Get the number of tokens.
- size_t GetTokenCount() const { return tokenCount_; }
-
- //@}
-
- //!@name Equality/inequality operators
- //@{
-
- //! Equality operator.
- /*!
- \note When any pointers are invalid, always returns false.
- */
- bool operator==(const GenericPointer& rhs) const {
- if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_)
- return false;
-
- for (size_t i = 0; i < tokenCount_; i++) {
- if (tokens_[i].index != rhs.tokens_[i].index ||
- tokens_[i].length != rhs.tokens_[i].length ||
- (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0))
- {
- return false;
- }
- }
-
- return true;
- }
-
- //! Inequality operator.
- /*!
- \note When any pointers are invalid, always returns true.
- */
- bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
-
- //@}
-
- //!@name Stringify
- //@{
-
- //! Stringify the pointer into string representation.
- /*!
- \tparam OutputStream Type of output stream.
- \param os The output stream.
- */
- template<typename OutputStream>
- bool Stringify(OutputStream& os) const {
- return Stringify<false, OutputStream>(os);
- }
-
- //! Stringify the pointer into URI fragment representation.
- /*!
- \tparam OutputStream Type of output stream.
- \param os The output stream.
- */
- template<typename OutputStream>
- bool StringifyUriFragment(OutputStream& os) const {
- return Stringify<true, OutputStream>(os);
- }
-
- //@}
-
- //!@name Create value
- //@{
-
- //! Create a value in a subtree.
- /*!
- If the value is not exist, it creates all parent values and a JSON Null value.
- So it always succeed and return the newly created or existing value.
-
- Remind that it may change types of parents according to tokens, so it
- potentially removes previously stored values. For example, if a document
- was an array, and "/foo" is used to create a value, then the document
- will be changed to an object, and all existing array elements are lost.
-
- \param root Root value of a DOM subtree to be resolved. It can be any value other than document root.
- \param allocator Allocator for creating the values if the specified value or its parents are not exist.
- \param alreadyExist If non-null, it stores whether the resolved value is already exist.
- \return The resolved newly created (a JSON Null value), or already exists value.
- */
- ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
- RAPIDJSON_ASSERT(IsValid());
- ValueType* v = &root;
- bool exist = true;
- for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
- if (v->IsArray() && t->name[0] == '-' && t->length == 1) {
- v->PushBack(ValueType().Move(), allocator);
- v = &((*v)[v->Size() - 1]);
- exist = false;
- }
- else {
- if (t->index == kPointerInvalidIndex) { // must be object name
- if (!v->IsObject())
- v->SetObject(); // Change to Object
- }
- else { // object name or array index
- if (!v->IsArray() && !v->IsObject())
- v->SetArray(); // Change to Array
- }
-
- if (v->IsArray()) {
- if (t->index >= v->Size()) {
- v->Reserve(t->index + 1, allocator);
- while (t->index >= v->Size())
- v->PushBack(ValueType().Move(), allocator);
- exist = false;
- }
- v = &((*v)[t->index]);
- }
- else {
- typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
- if (m == v->MemberEnd()) {
- v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
- v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
- exist = false;
- }
- else
- v = &m->value;
- }
- }
- }
-
- if (alreadyExist)
- *alreadyExist = exist;
-
- return *v;
- }
-
- //! Creates a value in a document.
- /*!
- \param document A document to be resolved.
- \param alreadyExist If non-null, it stores whether the resolved value is already exist.
- \return The resolved newly created, or already exists value.
- */
- template <typename stackAllocator>
- ValueType& Create(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, bool* alreadyExist = 0) const {
- return Create(document, document.GetAllocator(), alreadyExist);
- }
-
- //@}
-
- //!@name Query value
- //@{
-
- //! Query a value in a subtree.
- /*!
- \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
- \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
- \return Pointer to the value if it can be resolved. Otherwise null.
-
- \note
- There are only 3 situations when a value cannot be resolved:
- 1. A value in the path is not an array nor object.
- 2. An object value does not contain the token.
- 3. A token is out of range of an array value.
-
- Use unresolvedTokenIndex to retrieve the token index.
- */
- ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
- RAPIDJSON_ASSERT(IsValid());
- ValueType* v = &root;
- for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
- switch (v->GetType()) {
- case kObjectType:
- {
- typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
- if (m == v->MemberEnd())
- break;
- v = &m->value;
- }
- continue;
- case kArrayType:
- if (t->index == kPointerInvalidIndex || t->index >= v->Size())
- break;
- v = &((*v)[t->index]);
- continue;
- default:
- break;
- }
-
- // Error: unresolved token
- if (unresolvedTokenIndex)
- *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
- return 0;
- }
- return v;
- }
-
- //! Query a const value in a const subtree.
- /*!
- \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
- \return Pointer to the value if it can be resolved. Otherwise null.
- */
- const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const {
- return Get(const_cast<ValueType&>(root), unresolvedTokenIndex);
- }
-
- //@}
-
- //!@name Query a value with default
- //@{
-
- //! Query a value in a subtree with default value.
- /*!
- Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value.
- So that this function always succeed.
-
- \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
- \param defaultValue Default value to be cloned if the value was not exists.
- \param allocator Allocator for creating the values if the specified value or its parents are not exist.
- \see Create()
- */
- ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
- bool alreadyExist;
- Value& v = Create(root, allocator, &alreadyExist);
- return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
- }
-
- //! Query a value in a subtree with default null-terminated string.
- ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
- bool alreadyExist;
- Value& v = Create(root, allocator, &alreadyExist);
- return alreadyExist ? v : v.SetString(defaultValue, allocator);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Query a value in a subtree with default std::basic_string.
- ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
- bool alreadyExist;
- Value& v = Create(root, allocator, &alreadyExist);
- return alreadyExist ? v : v.SetString(defaultValue, allocator);
- }
-#endif
-
- //! Query a value in a subtree with default primitive value.
- /*!
- \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
- GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
- return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
- }
-
- //! Query a value in a document with default value.
- template <typename stackAllocator>
- ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& defaultValue) const {
- return GetWithDefault(document, defaultValue, document.GetAllocator());
- }
-
- //! Query a value in a document with default null-terminated string.
- template <typename stackAllocator>
- ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* defaultValue) const {
- return GetWithDefault(document, defaultValue, document.GetAllocator());
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Query a value in a document with default std::basic_string.
- template <typename stackAllocator>
- ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
- return GetWithDefault(document, defaultValue, document.GetAllocator());
- }
-#endif
-
- //! Query a value in a document with default primitive value.
- /*!
- \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
- */
- template <typename T, typename stackAllocator>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
- GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
- return GetWithDefault(document, defaultValue, document.GetAllocator());
- }
-
- //@}
-
- //!@name Set a value
- //@{
-
- //! Set a value in a subtree, with move semantics.
- /*!
- It creates all parents if they are not exist or types are different to the tokens.
- So this function always succeeds but potentially remove existing values.
-
- \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
- \param value Value to be set.
- \param allocator Allocator for creating the values if the specified value or its parents are not exist.
- \see Create()
- */
- ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
- return Create(root, allocator) = value;
- }
-
- //! Set a value in a subtree, with copy semantics.
- ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const {
- return Create(root, allocator).CopyFrom(value, allocator);
- }
-
- //! Set a null-terminated string in a subtree.
- ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const {
- return Create(root, allocator) = ValueType(value, allocator).Move();
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Set a std::basic_string in a subtree.
- ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
- return Create(root, allocator) = ValueType(value, allocator).Move();
- }
-#endif
-
- //! Set a primitive value in a subtree.
- /*!
- \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
- Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
- return Create(root, allocator) = ValueType(value).Move();
- }
-
- //! Set a value in a document, with move semantics.
- template <typename stackAllocator>
- ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
- return Create(document) = value;
- }
-
- //! Set a value in a document, with copy semantics.
- template <typename stackAllocator>
- ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const ValueType& value) const {
- return Create(document).CopyFrom(value, document.GetAllocator());
- }
-
- //! Set a null-terminated string in a document.
- template <typename stackAllocator>
- ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const Ch* value) const {
- return Create(document) = ValueType(value, document.GetAllocator()).Move();
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Sets a std::basic_string in a document.
- template <typename stackAllocator>
- ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
- return Create(document) = ValueType(value, document.GetAllocator()).Move();
- }
-#endif
-
- //! Set a primitive value in a document.
- /*!
- \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
- */
- template <typename T, typename stackAllocator>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
- Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
- return Create(document) = value;
- }
-
- //@}
-
- //!@name Swap a value
- //@{
-
- //! Swap a value with a value in a subtree.
- /*!
- It creates all parents if they are not exist or types are different to the tokens.
- So this function always succeeds but potentially remove existing values.
-
- \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
- \param value Value to be swapped.
- \param allocator Allocator for creating the values if the specified value or its parents are not exist.
- \see Create()
- */
- ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const {
- return Create(root, allocator).Swap(value);
- }
-
- //! Swap a value with a value in a document.
- template <typename stackAllocator>
- ValueType& Swap(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, ValueType& value) const {
- return Create(document).Swap(value);
- }
-
- //@}
-
- //! Erase a value in a subtree.
- /*!
- \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
- \return Whether the resolved value is found and erased.
-
- \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
- */
- bool Erase(ValueType& root) const {
- RAPIDJSON_ASSERT(IsValid());
- if (tokenCount_ == 0) // Cannot erase the root
- return false;
-
- ValueType* v = &root;
- const Token* last = tokens_ + (tokenCount_ - 1);
- for (const Token *t = tokens_; t != last; ++t) {
- switch (v->GetType()) {
- case kObjectType:
- {
- typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
- if (m == v->MemberEnd())
- return false;
- v = &m->value;
- }
- break;
- case kArrayType:
- if (t->index == kPointerInvalidIndex || t->index >= v->Size())
- return false;
- v = &((*v)[t->index]);
- break;
- default:
- return false;
- }
- }
-
- switch (v->GetType()) {
- case kObjectType:
- return v->EraseMember(GenericStringRef<Ch>(last->name, last->length));
- case kArrayType:
- if (last->index == kPointerInvalidIndex || last->index >= v->Size())
- return false;
- v->Erase(v->Begin() + last->index);
- return true;
- default:
- return false;
- }
- }
-
-private:
- //! Clone the content from rhs to this.
- /*!
- \param rhs Source pointer.
- \param extraToken Extra tokens to be allocated.
- \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated.
- \return Start of non-occupied name buffer, for storing extra names.
- */
- Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
- if (!allocator_) // allocator is independently owned.
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
-
- size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
- for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
- nameBufferSize += t->length;
-
- tokenCount_ = rhs.tokenCount_ + extraToken;
- tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch)));
- nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
- if (rhs.tokenCount_ > 0) {
- std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token));
- }
- if (nameBufferSize > 0) {
- std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch));
- }
-
- // Adjust pointers to name buffer
- std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_;
- for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t)
- t->name += diff;
-
- return nameBuffer_ + nameBufferSize;
- }
-
- //! Check whether a character should be percent-encoded.
- /*!
- According to RFC 3986 2.3 Unreserved Characters.
- \param c The character (code unit) to be tested.
- */
- bool NeedPercentEncode(Ch c) const {
- return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~');
- }
-
- //! Parse a JSON String or its URI fragment representation into tokens.
-#ifndef __clang__ // -Wdocumentation
- /*!
- \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated.
- \param length Length of the source string.
- \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped.
- */
-#endif
- void Parse(const Ch* source, size_t length) {
- RAPIDJSON_ASSERT(source != NULL);
- RAPIDJSON_ASSERT(nameBuffer_ == 0);
- RAPIDJSON_ASSERT(tokens_ == 0);
-
- // Create own allocator if user did not supply.
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
-
- // Count number of '/' as tokenCount
- tokenCount_ = 0;
- for (const Ch* s = source; s != source + length; s++)
- if (*s == '/')
- tokenCount_++;
-
- Token* token = tokens_ = static_cast<Token *>(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch)));
- Ch* name = nameBuffer_ = reinterpret_cast<Ch *>(tokens_ + tokenCount_);
- size_t i = 0;
-
- // Detect if it is a URI fragment
- bool uriFragment = false;
- if (source[i] == '#') {
- uriFragment = true;
- i++;
- }
-
- if (i != length && source[i] != '/') {
- parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus;
- goto error;
- }
-
- while (i < length) {
- RAPIDJSON_ASSERT(source[i] == '/');
- i++; // consumes '/'
-
- token->name = name;
- bool isNumber = true;
-
- while (i < length && source[i] != '/') {
- Ch c = source[i];
- if (uriFragment) {
- // Decoding percent-encoding for URI fragment
- if (c == '%') {
- PercentDecodeStream is(&source[i], source + length);
- GenericInsituStringStream<EncodingType> os(name);
- Ch* begin = os.PutBegin();
- if (!Transcoder<UTF8<>, EncodingType>().Validate(is, os) || !is.IsValid()) {
- parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding;
- goto error;
- }
- size_t len = os.PutEnd(begin);
- i += is.Tell() - 1;
- if (len == 1)
- c = *name;
- else {
- name += len;
- isNumber = false;
- i++;
- continue;
- }
- }
- else if (NeedPercentEncode(c)) {
- parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode;
- goto error;
- }
- }
-
- i++;
-
- // Escaping "~0" -> '~', "~1" -> '/'
- if (c == '~') {
- if (i < length) {
- c = source[i];
- if (c == '0') c = '~';
- else if (c == '1') c = '/';
- else {
- parseErrorCode_ = kPointerParseErrorInvalidEscape;
- goto error;
- }
- i++;
- }
- else {
- parseErrorCode_ = kPointerParseErrorInvalidEscape;
- goto error;
- }
- }
-
- // First check for index: all of characters are digit
- if (c < '0' || c > '9')
- isNumber = false;
-
- *name++ = c;
- }
- token->length = static_cast<SizeType>(name - token->name);
- if (token->length == 0)
- isNumber = false;
- *name++ = '\0'; // Null terminator
-
- // Second check for index: more than one digit cannot have leading zero
- if (isNumber && token->length > 1 && token->name[0] == '0')
- isNumber = false;
-
- // String to SizeType conversion
- SizeType n = 0;
- if (isNumber) {
- for (size_t j = 0; j < token->length; j++) {
- SizeType m = n * 10 + static_cast<SizeType>(token->name[j] - '0');
- if (m < n) { // overflow detection
- isNumber = false;
- break;
- }
- n = m;
- }
- }
-
- token->index = isNumber ? n : kPointerInvalidIndex;
- token++;
- }
-
- RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
- parseErrorCode_ = kPointerParseErrorNone;
- return;
-
- error:
- Allocator::Free(tokens_);
- nameBuffer_ = 0;
- tokens_ = 0;
- tokenCount_ = 0;
- parseErrorOffset_ = i;
- return;
- }
-
- //! Stringify to string or URI fragment representation.
- /*!
- \tparam uriFragment True for stringifying to URI fragment representation. False for string representation.
- \tparam OutputStream type of output stream.
- \param os The output stream.
- */
- template<bool uriFragment, typename OutputStream>
- bool Stringify(OutputStream& os) const {
- RAPIDJSON_ASSERT(IsValid());
-
- if (uriFragment)
- os.Put('#');
-
- for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
- os.Put('/');
- for (size_t j = 0; j < t->length; j++) {
- Ch c = t->name[j];
- if (c == '~') {
- os.Put('~');
- os.Put('0');
- }
- else if (c == '/') {
- os.Put('~');
- os.Put('1');
- }
- else if (uriFragment && NeedPercentEncode(c)) {
- // Transcode to UTF8 sequence
- GenericStringStream<typename ValueType::EncodingType> source(&t->name[j]);
- PercentEncodeStream<OutputStream> target(os);
- if (!Transcoder<EncodingType, UTF8<> >().Validate(source, target))
- return false;
- j += source.Tell() - 1;
- }
- else
- os.Put(c);
- }
- }
- return true;
- }
-
- //! A helper stream for decoding a percent-encoded sequence into code unit.
- /*!
- This stream decodes %XY triplet into code unit (0-255).
- If it encounters invalid characters, it sets output code unit as 0 and
- mark invalid, and to be checked by IsValid().
- */
- class PercentDecodeStream {
- public:
- typedef typename ValueType::Ch Ch;
-
- //! Constructor
- /*!
- \param source Start of the stream
- \param end Past-the-end of the stream.
- */
- PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {}
-
- Ch Take() {
- if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet
- valid_ = false;
- return 0;
- }
- src_++;
- Ch c = 0;
- for (int j = 0; j < 2; j++) {
- c = static_cast<Ch>(c << 4);
- Ch h = *src_;
- if (h >= '0' && h <= '9') c = static_cast<Ch>(c + h - '0');
- else if (h >= 'A' && h <= 'F') c = static_cast<Ch>(c + h - 'A' + 10);
- else if (h >= 'a' && h <= 'f') c = static_cast<Ch>(c + h - 'a' + 10);
- else {
- valid_ = false;
- return 0;
- }
- src_++;
- }
- return c;
- }
-
- size_t Tell() const { return static_cast<size_t>(src_ - head_); }
- bool IsValid() const { return valid_; }
-
- private:
- const Ch* src_; //!< Current read position.
- const Ch* head_; //!< Original head of the string.
- const Ch* end_; //!< Past-the-end position.
- bool valid_; //!< Whether the parsing is valid.
- };
-
- //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence.
- template <typename OutputStream>
- class PercentEncodeStream {
- public:
- PercentEncodeStream(OutputStream& os) : os_(os) {}
- void Put(char c) { // UTF-8 must be byte
- unsigned char u = static_cast<unsigned char>(c);
- static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- os_.Put('%');
- os_.Put(hexDigits[u >> 4]);
- os_.Put(hexDigits[u & 15]);
- }
- private:
- OutputStream& os_;
- };
-
- Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
- Allocator* ownAllocator_; //!< Allocator owned by this Pointer.
- Ch* nameBuffer_; //!< A buffer containing all names in tokens.
- Token* tokens_; //!< A list of tokens.
- size_t tokenCount_; //!< Number of tokens in tokens_.
- size_t parseErrorOffset_; //!< Offset in code unit when parsing fail.
- PointerParseErrorCode parseErrorCode_; //!< Parsing error code.
-};
-
-//! GenericPointer for Value (UTF-8, default allocator).
-typedef GenericPointer<Value> Pointer;
-
-//!@name Helper functions for GenericPointer
-//@{
-
-//////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::AllocatorType& a) {
- return pointer.Create(root, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Create(root, a);
-}
-
-// No allocator parameter
-
-template <typename DocumentType>
-typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer) {
- return pointer.Create(document);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Create(document);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
- return pointer.Get(root, unresolvedTokenIndex);
-}
-
-template <typename T>
-const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
- return pointer.Get(root, unresolvedTokenIndex);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
-}
-
-template <typename T, typename CharType, size_t N>
-const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
- return pointer.GetWithDefault(root, defaultValue, a);
-}
-
-template <typename T>
-typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
- return pointer.GetWithDefault(root, defaultValue, a);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename T>
-typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
- return pointer.GetWithDefault(root, defaultValue, a);
-}
-#endif
-
-template <typename T, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
-GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
- return pointer.GetWithDefault(root, defaultValue, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
-}
-#endif
-
-template <typename T, typename CharType, size_t N, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
-GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
-}
-
-// No allocator parameter
-
-template <typename DocumentType>
-typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& defaultValue) {
- return pointer.GetWithDefault(document, defaultValue);
-}
-
-template <typename DocumentType>
-typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* defaultValue) {
- return pointer.GetWithDefault(document, defaultValue);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename DocumentType>
-typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
- return pointer.GetWithDefault(document, defaultValue);
-}
-#endif
-
-template <typename DocumentType, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
-GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
- return pointer.GetWithDefault(document, defaultValue);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
-}
-#endif
-
-template <typename DocumentType, typename CharType, size_t N, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
-GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
- return pointer.Set(root, value, a);
-}
-
-template <typename T>
-typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) {
- return pointer.Set(root, value, a);
-}
-
-template <typename T>
-typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const typename T::Ch* value, typename T::AllocatorType& a) {
- return pointer.Set(root, value, a);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename T>
-typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
- return pointer.Set(root, value, a);
-}
-#endif
-
-template <typename T, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
-SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
- return pointer.Set(root, value, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
-}
-#endif
-
-template <typename T, typename CharType, size_t N, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
-SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
-}
-
-// No allocator parameter
-
-template <typename DocumentType>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
- return pointer.Set(document, value);
-}
-
-template <typename DocumentType>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::ValueType& value) {
- return pointer.Set(document, value);
-}
-
-template <typename DocumentType>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const typename DocumentType::Ch* value) {
- return pointer.Set(document, value);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename DocumentType>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
- return pointer.Set(document, value);
-}
-#endif
-
-template <typename DocumentType, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
-SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
- return pointer.Set(document, value);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
-}
-#endif
-
-template <typename DocumentType, typename CharType, size_t N, typename T2>
-RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
-SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, typename T::ValueType& value, typename T::AllocatorType& a) {
- return pointer.Swap(root, value, a);
-}
-
-template <typename T, typename CharType, size_t N>
-typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Swap(root, value, a);
-}
-
-template <typename DocumentType>
-typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, typename DocumentType::ValueType& value) {
- return pointer.Swap(document, value);
-}
-
-template <typename DocumentType, typename CharType, size_t N>
-typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) {
- return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Swap(document, value);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-template <typename T>
-bool EraseValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer) {
- return pointer.Erase(root);
-}
-
-template <typename T, typename CharType, size_t N>
-bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
- return GenericPointer<typename T::ValueType>(source, N - 1).Erase(root);
-}
-
-//@}
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_POINTER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_PRETTYWRITER_H_
-#define RAPIDJSON_PRETTYWRITER_H_
-
-#include "writer.h"
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Combination of PrettyWriter format flags.
-/*! \see PrettyWriter::SetFormatOptions
- */
-enum PrettyFormatOptions {
- kFormatDefault = 0, //!< Default pretty formatting.
- kFormatSingleLineArray = 1 //!< Format arrays on a single line.
-};
-
-//! Writer with indentation and spacing.
-/*!
- \tparam OutputStream Type of ouptut os.
- \tparam SourceEncoding Encoding of source string.
- \tparam TargetEncoding Encoding of output stream.
- \tparam StackAllocator Type of allocator for allocating memory of stack.
-*/
-template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
-class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
-public:
- typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
- typedef typename Base::Ch Ch;
-
- //! Constructor
- /*! \param os Output stream.
- \param allocator User supplied allocator. If it is null, it will create a private one.
- \param levelDepth Initial capacity of stack.
- */
- explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
- Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
-
-
- explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
- Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
-
- //! Set custom indentation.
- /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
- \param indentCharCount Number of indent characters for each indentation level.
- \note The default indentation is 4 spaces.
- */
- PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
- RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
- indentChar_ = indentChar;
- indentCharCount_ = indentCharCount;
- return *this;
- }
-
- //! Set pretty writer formatting options.
- /*! \param options Formatting options.
- */
- PrettyWriter& SetFormatOptions(PrettyFormatOptions options) {
- formatOptions_ = options;
- return *this;
- }
-
- /*! @name Implementation of Handler
- \see Handler
- */
- //@{
-
- bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
- bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
- bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
- bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
- bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
- bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
- bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
-
- bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
- (void)copy;
- PrettyPrefix(kNumberType);
- return Base::WriteString(str, length);
- }
-
- bool String(const Ch* str, SizeType length, bool copy = false) {
- (void)copy;
- PrettyPrefix(kStringType);
- return Base::WriteString(str, length);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool String(const std::basic_string<Ch>& str) {
- return String(str.data(), SizeType(str.size()));
- }
-#endif
-
- bool StartObject() {
- PrettyPrefix(kObjectType);
- new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
- return Base::WriteStartObject();
- }
-
- bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool Key(const std::basic_string<Ch>& str) {
- return Key(str.data(), SizeType(str.size()));
- }
-#endif
-
- bool EndObject(SizeType memberCount = 0) {
- (void)memberCount;
- RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
- RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
- bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
-
- if (!empty) {
- Base::os_->Put('\n');
- WriteIndent();
- }
- bool ret = Base::WriteEndObject();
- (void)ret;
- RAPIDJSON_ASSERT(ret == true);
- if (Base::level_stack_.Empty()) // end of json text
- Base::os_->Flush();
- return true;
- }
-
- bool StartArray() {
- PrettyPrefix(kArrayType);
- new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
- return Base::WriteStartArray();
- }
-
- bool EndArray(SizeType memberCount = 0) {
- (void)memberCount;
- RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
- RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
- bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
-
- if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
- Base::os_->Put('\n');
- WriteIndent();
- }
- bool ret = Base::WriteEndArray();
- (void)ret;
- RAPIDJSON_ASSERT(ret == true);
- if (Base::level_stack_.Empty()) // end of json text
- Base::os_->Flush();
- return true;
- }
-
- //@}
-
- /*! @name Convenience extensions */
- //@{
-
- //! Simpler but slower overload.
- bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
- bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
-
- //@}
-
- //! Write a raw JSON value.
- /*!
- For user to write a stringified JSON as a value.
-
- \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
- \param length Length of the json.
- \param type Type of the root of json.
- \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
- */
- bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
-
-protected:
- void PrettyPrefix(Type type) {
- (void)type;
- if (Base::level_stack_.GetSize() != 0) { // this value is not at root
- typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
-
- if (level->inArray) {
- if (level->valueCount > 0) {
- Base::os_->Put(','); // add comma if it is not the first element in array
- if (formatOptions_ & kFormatSingleLineArray)
- Base::os_->Put(' ');
- }
-
- if (!(formatOptions_ & kFormatSingleLineArray)) {
- Base::os_->Put('\n');
- WriteIndent();
- }
- }
- else { // in object
- if (level->valueCount > 0) {
- if (level->valueCount % 2 == 0) {
- Base::os_->Put(',');
- Base::os_->Put('\n');
- }
- else {
- Base::os_->Put(':');
- Base::os_->Put(' ');
- }
- }
- else
- Base::os_->Put('\n');
-
- if (level->valueCount % 2 == 0)
- WriteIndent();
- }
- if (!level->inArray && level->valueCount % 2 == 0)
- RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
- level->valueCount++;
- }
- else {
- RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
- Base::hasRoot_ = true;
- }
- }
-
- void WriteIndent() {
- size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
- PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
- }
-
- Ch indentChar_;
- unsigned indentCharCount_;
- PrettyFormatOptions formatOptions_;
-
-private:
- // Prohibit copy constructor & assignment operator.
- PrettyWriter(const PrettyWriter&);
- PrettyWriter& operator=(const PrettyWriter&);
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_RAPIDJSON_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_RAPIDJSON_H_
-#define RAPIDJSON_RAPIDJSON_H_
-
-/*!\file rapidjson.h
- \brief common definitions and configuration
-
- \see RAPIDJSON_CONFIG
- */
-
-/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
- \brief Configuration macros for library features
-
- Some RapidJSON features are configurable to adapt the library to a wide
- variety of platforms, environments and usage scenarios. Most of the
- features can be configured in terms of overriden or predefined
- preprocessor macros at compile-time.
-
- Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
-
- \note These macros should be given on the compiler command-line
- (where applicable) to avoid inconsistent values when compiling
- different translation units of a single application.
- */
-
-#include <cstdlib> // malloc(), realloc(), free(), size_t
-#include <cstring> // memset(), memcpy(), memmove(), memcmp()
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_VERSION_STRING
-//
-// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
-//
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-// token stringification
-#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
-#define RAPIDJSON_DO_STRINGIFY(x) #x
-//!@endcond
-
-/*! \def RAPIDJSON_MAJOR_VERSION
- \ingroup RAPIDJSON_CONFIG
- \brief Major version of RapidJSON in integer.
-*/
-/*! \def RAPIDJSON_MINOR_VERSION
- \ingroup RAPIDJSON_CONFIG
- \brief Minor version of RapidJSON in integer.
-*/
-/*! \def RAPIDJSON_PATCH_VERSION
- \ingroup RAPIDJSON_CONFIG
- \brief Patch version of RapidJSON in integer.
-*/
-/*! \def RAPIDJSON_VERSION_STRING
- \ingroup RAPIDJSON_CONFIG
- \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
-*/
-#define RAPIDJSON_MAJOR_VERSION 1
-#define RAPIDJSON_MINOR_VERSION 1
-#define RAPIDJSON_PATCH_VERSION 0
-#define RAPIDJSON_VERSION_STRING \
- RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_NAMESPACE_(BEGIN|END)
-/*! \def RAPIDJSON_NAMESPACE
- \ingroup RAPIDJSON_CONFIG
- \brief provide custom rapidjson namespace
-
- In order to avoid symbol clashes and/or "One Definition Rule" errors
- between multiple inclusions of (different versions of) RapidJSON in
- a single binary, users can customize the name of the main RapidJSON
- namespace.
-
- In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
- to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple
- levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
- RAPIDJSON_NAMESPACE_END need to be defined as well:
-
- \code
- // in some .cpp file
- #define RAPIDJSON_NAMESPACE my::rapidjson
- #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
- #define RAPIDJSON_NAMESPACE_END } }
- #include "rapidjson/..."
- \endcode
-
- \see rapidjson
- */
-/*! \def RAPIDJSON_NAMESPACE_BEGIN
- \ingroup RAPIDJSON_CONFIG
- \brief provide custom rapidjson namespace (opening expression)
- \see RAPIDJSON_NAMESPACE
-*/
-/*! \def RAPIDJSON_NAMESPACE_END
- \ingroup RAPIDJSON_CONFIG
- \brief provide custom rapidjson namespace (closing expression)
- \see RAPIDJSON_NAMESPACE
-*/
-#ifndef RAPIDJSON_NAMESPACE
-#define RAPIDJSON_NAMESPACE rapidjson
-#endif
-#ifndef RAPIDJSON_NAMESPACE_BEGIN
-#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
-#endif
-#ifndef RAPIDJSON_NAMESPACE_END
-#define RAPIDJSON_NAMESPACE_END }
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_HAS_STDSTRING
-
-#ifndef RAPIDJSON_HAS_STDSTRING
-#ifdef RAPIDJSON_DOXYGEN_RUNNING
-#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
-#else
-#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
-#endif
-/*! \def RAPIDJSON_HAS_STDSTRING
- \ingroup RAPIDJSON_CONFIG
- \brief Enable RapidJSON support for \c std::string
-
- By defining this preprocessor symbol to \c 1, several convenience functions for using
- \ref rapidjson::GenericValue with \c std::string are enabled, especially
- for construction and comparison.
-
- \hideinitializer
-*/
-#endif // !defined(RAPIDJSON_HAS_STDSTRING)
-
-#if RAPIDJSON_HAS_STDSTRING
-#include <string>
-#endif // RAPIDJSON_HAS_STDSTRING
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_NO_INT64DEFINE
-
-/*! \def RAPIDJSON_NO_INT64DEFINE
- \ingroup RAPIDJSON_CONFIG
- \brief Use external 64-bit integer types.
-
- RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types
- to be available at global scope.
-
- If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
- prevent RapidJSON from defining its own types.
-*/
-#ifndef RAPIDJSON_NO_INT64DEFINE
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
-#include "msinttypes/stdint.h"
-#include "msinttypes/inttypes.h"
-#else
-// Other compilers should have this.
-#include <stdint.h>
-#include <inttypes.h>
-#endif
-//!@endcond
-#ifdef RAPIDJSON_DOXYGEN_RUNNING
-#define RAPIDJSON_NO_INT64DEFINE
-#endif
-#endif // RAPIDJSON_NO_INT64TYPEDEF
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_FORCEINLINE
-
-#ifndef RAPIDJSON_FORCEINLINE
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#if defined(_MSC_VER) && defined(NDEBUG)
-#define RAPIDJSON_FORCEINLINE __forceinline
-#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
-#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
-#else
-#define RAPIDJSON_FORCEINLINE
-#endif
-//!@endcond
-#endif // RAPIDJSON_FORCEINLINE
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ENDIAN
-#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
-#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
-
-//! Endianness of the machine.
-/*!
- \def RAPIDJSON_ENDIAN
- \ingroup RAPIDJSON_CONFIG
-
- GCC 4.6 provided macro for detecting endianness of the target machine. But other
- compilers may not have this. User can define RAPIDJSON_ENDIAN to either
- \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
-
- Default detection implemented with reference to
- \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
- \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
-*/
-#ifndef RAPIDJSON_ENDIAN
-// Detect with GCC 4.6's macro
-# ifdef __BYTE_ORDER__
-# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
-# else
-# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
-# endif // __BYTE_ORDER__
-// Detect with GLIBC's endian.h
-# elif defined(__GLIBC__)
-# include <endian.h>
-# if (__BYTE_ORDER == __LITTLE_ENDIAN)
-# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif (__BYTE_ORDER == __BIG_ENDIAN)
-# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
-# else
-# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
-# endif // __GLIBC__
-// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
-# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
-# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
-# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
-// Detect with architecture macros
-# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
-# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
-# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
-# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif defined(_MSC_VER) && defined(_M_ARM)
-# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
-# define RAPIDJSON_ENDIAN
-# else
-# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
-# endif
-#endif // RAPIDJSON_ENDIAN
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_64BIT
-
-//! Whether using 64-bit architecture
-#ifndef RAPIDJSON_64BIT
-#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
-#define RAPIDJSON_64BIT 1
-#else
-#define RAPIDJSON_64BIT 0
-#endif
-#endif // RAPIDJSON_64BIT
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ALIGN
-
-//! Data alignment of the machine.
-/*! \ingroup RAPIDJSON_CONFIG
- \param x pointer to align
-
- Some machines require strict data alignment. Currently the default uses 4 bytes
- alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
- User can customize by defining the RAPIDJSON_ALIGN function macro.
-*/
-#ifndef RAPIDJSON_ALIGN
-#if RAPIDJSON_64BIT == 1
-#define RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
-#else
-#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
-#endif
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_UINT64_C2
-
-//! Construct a 64-bit literal by a pair of 32-bit integer.
-/*!
- 64-bit literal with or without ULL suffix is prone to compiler warnings.
- UINT64_C() is C macro which cause compilation problems.
- Use this macro to define 64-bit constants by a pair of 32-bit integer.
-*/
-#ifndef RAPIDJSON_UINT64_C2
-#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_48BITPOINTER_OPTIMIZATION
-
-//! Use only lower 48-bit address for some pointers.
-/*!
- \ingroup RAPIDJSON_CONFIG
-
- This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
- The higher 16-bit can be used for storing other data.
- \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
-*/
-#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
-#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
-#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
-#else
-#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
-#endif
-#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
-
-#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
-#if RAPIDJSON_64BIT != 1
-#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
-#endif
-#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
-#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
-#else
-#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
-#define RAPIDJSON_GETPOINTER(type, p) (p)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
-
-/*! \def RAPIDJSON_SIMD
- \ingroup RAPIDJSON_CONFIG
- \brief Enable SSE2/SSE4.2 optimization.
-
- RapidJSON supports optimized implementations for some parsing operations
- based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
- processors.
-
- To enable these optimizations, two different symbols can be defined;
- \code
- // Enable SSE2 optimization.
- #define RAPIDJSON_SSE2
-
- // Enable SSE4.2 optimization.
- #define RAPIDJSON_SSE42
- \endcode
-
- \c RAPIDJSON_SSE42 takes precedence, if both are defined.
-
- If any of these symbols is defined, RapidJSON defines the macro
- \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
-*/
-#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
- || defined(RAPIDJSON_DOXYGEN_RUNNING)
-#define RAPIDJSON_SIMD
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_NO_SIZETYPEDEFINE
-
-#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
-/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
- \ingroup RAPIDJSON_CONFIG
- \brief User-provided \c SizeType definition.
-
- In order to avoid using 32-bit size types for indexing strings and arrays,
- define this preprocessor symbol and provide the type rapidjson::SizeType
- before including RapidJSON:
- \code
- #define RAPIDJSON_NO_SIZETYPEDEFINE
- namespace rapidjson { typedef ::std::size_t SizeType; }
- #include "rapidjson/..."
- \endcode
-
- \see rapidjson::SizeType
-*/
-#ifdef RAPIDJSON_DOXYGEN_RUNNING
-#define RAPIDJSON_NO_SIZETYPEDEFINE
-#endif
-RAPIDJSON_NAMESPACE_BEGIN
-//! Size type (for string lengths, array sizes, etc.)
-/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
- instead of using \c size_t. Users may override the SizeType by defining
- \ref RAPIDJSON_NO_SIZETYPEDEFINE.
-*/
-typedef unsigned SizeType;
-RAPIDJSON_NAMESPACE_END
-#endif
-
-// always import std::size_t to rapidjson namespace
-RAPIDJSON_NAMESPACE_BEGIN
-using std::size_t;
-RAPIDJSON_NAMESPACE_END
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ASSERT
-
-//! Assertion.
-/*! \ingroup RAPIDJSON_CONFIG
- By default, rapidjson uses C \c assert() for internal assertions.
- User can override it by defining RAPIDJSON_ASSERT(x) macro.
-
- \note Parsing errors are handled and can be customized by the
- \ref RAPIDJSON_ERRORS APIs.
-*/
-#ifndef RAPIDJSON_ASSERT
-#include <cassert>
-#define RAPIDJSON_ASSERT(x) assert(x)
-#endif // RAPIDJSON_ASSERT
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_STATIC_ASSERT
-
-// Adopt from boost
-#ifndef RAPIDJSON_STATIC_ASSERT
-#ifndef __clang__
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#endif
-RAPIDJSON_NAMESPACE_BEGIN
-template <bool x> struct STATIC_ASSERTION_FAILURE;
-template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
-template<int x> struct StaticAssertTest {};
-RAPIDJSON_NAMESPACE_END
-
-#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
-#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
-#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
-
-#if defined(__GNUC__)
-#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
-#else
-#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
-#endif
-#ifndef __clang__
-//!@endcond
-#endif
-
-/*! \def RAPIDJSON_STATIC_ASSERT
- \brief (Internal) macro to check for conditions at compile-time
- \param x compile-time condition
- \hideinitializer
- */
-#define RAPIDJSON_STATIC_ASSERT(x) \
- typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
- sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
- RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
-
-//! Compiler branching hint for expression with high probability to be true.
-/*!
- \ingroup RAPIDJSON_CONFIG
- \param x Boolean expression likely to be true.
-*/
-#ifndef RAPIDJSON_LIKELY
-#if defined(__GNUC__) || defined(__clang__)
-#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
-#else
-#define RAPIDJSON_LIKELY(x) (x)
-#endif
-#endif
-
-//! Compiler branching hint for expression with low probability to be true.
-/*!
- \ingroup RAPIDJSON_CONFIG
- \param x Boolean expression unlikely to be true.
-*/
-#ifndef RAPIDJSON_UNLIKELY
-#if defined(__GNUC__) || defined(__clang__)
-#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
-#else
-#define RAPIDJSON_UNLIKELY(x) (x)
-#endif
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-
-#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
-#define RAPIDJSON_MULTILINEMACRO_END \
-} while((void)0, 0)
-
-// adopted from Boost
-#define RAPIDJSON_VERSION_CODE(x,y,z) \
- (((x)*100000) + ((y)*100) + (z))
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
-
-#if defined(__GNUC__)
-#define RAPIDJSON_GNUC \
- RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
-#endif
-
-#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
-
-#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
-#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
-#define RAPIDJSON_DIAG_OFF(x) \
- RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
-
-// push/pop support in Clang and GCC>=4.6
-#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
-#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
-#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
-#else // GCC >= 4.2, < 4.6
-#define RAPIDJSON_DIAG_PUSH /* ignored */
-#define RAPIDJSON_DIAG_POP /* ignored */
-#endif
-
-#elif defined(_MSC_VER)
-
-// pragma (MSVC specific)
-#define RAPIDJSON_PRAGMA(x) __pragma(x)
-#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
-
-#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
-#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
-#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
-
-#else
-
-#define RAPIDJSON_DIAG_OFF(x) /* ignored */
-#define RAPIDJSON_DIAG_PUSH /* ignored */
-#define RAPIDJSON_DIAG_POP /* ignored */
-
-#endif // RAPIDJSON_DIAG_*
-
-///////////////////////////////////////////////////////////////////////////////
-// C++11 features
-
-#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#if defined(__clang__)
-#if __has_feature(cxx_rvalue_references) && \
- (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
-#else
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
-#endif
-#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
- (defined(_MSC_VER) && _MSC_VER >= 1600)
-
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
-#else
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
-#endif
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
-
-#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
-#if defined(__clang__)
-#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
-#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
-// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
-#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
-#else
-#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
-#endif
-#endif
-#if RAPIDJSON_HAS_CXX11_NOEXCEPT
-#define RAPIDJSON_NOEXCEPT noexcept
-#else
-#define RAPIDJSON_NOEXCEPT /* noexcept */
-#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
-
-// no automatic detection, yet
-#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
-#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
-#endif
-
-#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
-#if defined(__clang__)
-#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
-#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
- (defined(_MSC_VER) && _MSC_VER >= 1700)
-#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
-#else
-#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
-#endif
-#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
-
-//!@endcond
-
-///////////////////////////////////////////////////////////////////////////////
-// new/delete
-
-#ifndef RAPIDJSON_NEW
-///! customization point for global \c new
-#define RAPIDJSON_NEW(x) new x
-#endif
-#ifndef RAPIDJSON_DELETE
-///! customization point for global \c delete
-#define RAPIDJSON_DELETE(x) delete x
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Type
-
-/*! \namespace rapidjson
- \brief main RapidJSON namespace
- \see RAPIDJSON_NAMESPACE
-*/
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Type of JSON value
-enum Type {
- kNullType = 0, //!< null
- kFalseType = 1, //!< false
- kTrueType = 2, //!< true
- kObjectType = 3, //!< object
- kArrayType = 4, //!< array
- kStringType = 5, //!< string
- kNumberType = 6 //!< number
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_RAPIDJSON_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_READER_H_
-#define RAPIDJSON_READER_H_
-
-/*! \file reader.h */
-
-#include "allocators.h"
-#include "stream.h"
-#include "encodedstream.h"
-#include "internal/meta.h"
-#include "internal/stack.h"
-#include "internal/strtod.h"
-#include <limits>
-
-#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
-#include <intrin.h>
-#pragma intrinsic(_BitScanForward)
-#endif
-#ifdef RAPIDJSON_SSE42
-#include <nmmintrin.h>
-#elif defined(RAPIDJSON_SSE2)
-#include <emmintrin.h>
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-RAPIDJSON_DIAG_OFF(4702) // unreachable code
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(old-style-cast)
-RAPIDJSON_DIAG_OFF(padded)
-RAPIDJSON_DIAG_OFF(switch-enum)
-#endif
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#define RAPIDJSON_NOTHING /* deliberately empty */
-#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
-#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
- RAPIDJSON_MULTILINEMACRO_BEGIN \
- if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \
- RAPIDJSON_MULTILINEMACRO_END
-#endif
-#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
-//!@endcond
-
-/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
- \ingroup RAPIDJSON_ERRORS
- \brief Macro to indicate a parse error.
- \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
- \param offset position of the error in JSON input (\c size_t)
-
- This macros can be used as a customization point for the internal
- error handling mechanism of RapidJSON.
-
- A common usage model is to throw an exception instead of requiring the
- caller to explicitly check the \ref rapidjson::GenericReader::Parse's
- return value:
-
- \code
- #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
- throw ParseException(parseErrorCode, #parseErrorCode, offset)
-
- #include <stdexcept> // std::runtime_error
- #include "rapidjson/error/error.h" // rapidjson::ParseResult
-
- struct ParseException : std::runtime_error, rapidjson::ParseResult {
- ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
- : std::runtime_error(msg), ParseResult(code, offset) {}
- };
-
- #include "rapidjson/reader.h"
- \endcode
-
- \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
- */
-#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
-#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
- RAPIDJSON_MULTILINEMACRO_BEGIN \
- RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
- SetParseError(parseErrorCode, offset); \
- RAPIDJSON_MULTILINEMACRO_END
-#endif
-
-/*! \def RAPIDJSON_PARSE_ERROR
- \ingroup RAPIDJSON_ERRORS
- \brief (Internal) macro to indicate and handle a parse error.
- \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
- \param offset position of the error in JSON input (\c size_t)
-
- Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
-
- \see RAPIDJSON_PARSE_ERROR_NORETURN
- \hideinitializer
- */
-#ifndef RAPIDJSON_PARSE_ERROR
-#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
- RAPIDJSON_MULTILINEMACRO_BEGIN \
- RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
- RAPIDJSON_MULTILINEMACRO_END
-#endif
-
-#include "error/error.h" // ParseErrorCode, ParseResult
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// ParseFlag
-
-/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
- \ingroup RAPIDJSON_CONFIG
- \brief User-defined kParseDefaultFlags definition.
-
- User can define this as any \c ParseFlag combinations.
-*/
-#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
-#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
-#endif
-
-//! Combination of parseFlags
-/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
- */
-enum ParseFlag {
- kParseNoFlags = 0, //!< No flags are set.
- kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
- kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
- kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
- kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
- kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
- kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
- kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
- kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
- kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles.
- kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Handler
-
-/*! \class rapidjson::Handler
- \brief Concept for receiving events from GenericReader upon parsing.
- The functions return true if no error occurs. If they return false,
- the event publisher should terminate the process.
-\code
-concept Handler {
- typename Ch;
-
- bool Null();
- bool Bool(bool b);
- bool Int(int i);
- bool Uint(unsigned i);
- bool Int64(int64_t i);
- bool Uint64(uint64_t i);
- bool Double(double d);
- /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
- bool RawNumber(const Ch* str, SizeType length, bool copy);
- bool String(const Ch* str, SizeType length, bool copy);
- bool StartObject();
- bool Key(const Ch* str, SizeType length, bool copy);
- bool EndObject(SizeType memberCount);
- bool StartArray();
- bool EndArray(SizeType elementCount);
-};
-\endcode
-*/
-///////////////////////////////////////////////////////////////////////////////
-// BaseReaderHandler
-
-//! Default implementation of Handler.
-/*! This can be used as base class of any reader handler.
- \note implements Handler concept
-*/
-template<typename Encoding = UTF8<>, typename Derived = void>
-struct BaseReaderHandler {
- typedef typename Encoding::Ch Ch;
-
- typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
-
- bool Default() { return true; }
- bool Null() { return static_cast<Override&>(*this).Default(); }
- bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
- bool Int(int) { return static_cast<Override&>(*this).Default(); }
- bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
- bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
- bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
- bool Double(double) { return static_cast<Override&>(*this).Default(); }
- /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
- bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
- bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
- bool StartObject() { return static_cast<Override&>(*this).Default(); }
- bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
- bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
- bool StartArray() { return static_cast<Override&>(*this).Default(); }
- bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// StreamLocalCopy
-
-namespace internal {
-
-template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
-class StreamLocalCopy;
-
-//! Do copy optimization.
-template<typename Stream>
-class StreamLocalCopy<Stream, 1> {
-public:
- StreamLocalCopy(Stream& original) : s(original), original_(original) {}
- ~StreamLocalCopy() { original_ = s; }
-
- Stream s;
-
-private:
- StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
-
- Stream& original_;
-};
-
-//! Keep reference.
-template<typename Stream>
-class StreamLocalCopy<Stream, 0> {
-public:
- StreamLocalCopy(Stream& original) : s(original) {}
-
- Stream& s;
-
-private:
- StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
-};
-
-} // namespace internal
-
-///////////////////////////////////////////////////////////////////////////////
-// SkipWhitespace
-
-//! Skip the JSON white spaces in a stream.
-/*! \param is A input stream for skipping white spaces.
- \note This function has SSE2/SSE4.2 specialization.
-*/
-template<typename InputStream>
-void SkipWhitespace(InputStream& is) {
- internal::StreamLocalCopy<InputStream> copy(is);
- InputStream& s(copy.s);
-
- typename InputStream::Ch c;
- while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t')
- s.Take();
-}
-
-inline const char* SkipWhitespace(const char* p, const char* end) {
- while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
- ++p;
- return p;
-}
-
-#ifdef RAPIDJSON_SSE42
-//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
-inline const char *SkipWhitespace_SIMD(const char* p) {
- // Fast return for single non-whitespace
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // 16-byte align to the next boundary
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
- while (p != nextAligned)
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // The rest of string using SIMD
- static const char whitespace[16] = " \n\r\t";
- const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
-
- for (;; p += 16) {
- const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
- const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
- if (r != 0) { // some of characters is non-whitespace
-#ifdef _MSC_VER // Find the index of first non-whitespace
- unsigned long offset;
- _BitScanForward(&offset, r);
- return p + offset;
-#else
- return p + __builtin_ffs(r) - 1;
-#endif
- }
- }
-}
-
-inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
- // Fast return for single non-whitespace
- if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
- ++p;
- else
- return p;
-
- // The middle of string using SIMD
- static const char whitespace[16] = " \n\r\t";
- const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
-
- for (; p <= end - 16; p += 16) {
- const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
- const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
- if (r != 0) { // some of characters is non-whitespace
-#ifdef _MSC_VER // Find the index of first non-whitespace
- unsigned long offset;
- _BitScanForward(&offset, r);
- return p + offset;
-#else
- return p + __builtin_ffs(r) - 1;
-#endif
- }
- }
-
- return SkipWhitespace(p, end);
-}
-
-#elif defined(RAPIDJSON_SSE2)
-
-//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
-inline const char *SkipWhitespace_SIMD(const char* p) {
- // Fast return for single non-whitespace
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // 16-byte align to the next boundary
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
- while (p != nextAligned)
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // The rest of string
- #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
- static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
- #undef C16
-
- const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
- const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
- const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
- const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
-
- for (;; p += 16) {
- const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
- __m128i x = _mm_cmpeq_epi8(s, w0);
- x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
- x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
- x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
- unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
- if (r != 0) { // some of characters may be non-whitespace
-#ifdef _MSC_VER // Find the index of first non-whitespace
- unsigned long offset;
- _BitScanForward(&offset, r);
- return p + offset;
-#else
- return p + __builtin_ffs(r) - 1;
-#endif
- }
- }
-}
-
-inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
- // Fast return for single non-whitespace
- if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
- ++p;
- else
- return p;
-
- // The rest of string
- #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
- static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
- #undef C16
-
- const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
- const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
- const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
- const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
-
- for (; p <= end - 16; p += 16) {
- const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
- __m128i x = _mm_cmpeq_epi8(s, w0);
- x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
- x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
- x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
- unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
- if (r != 0) { // some of characters may be non-whitespace
-#ifdef _MSC_VER // Find the index of first non-whitespace
- unsigned long offset;
- _BitScanForward(&offset, r);
- return p + offset;
-#else
- return p + __builtin_ffs(r) - 1;
-#endif
- }
- }
-
- return SkipWhitespace(p, end);
-}
-
-#endif // RAPIDJSON_SSE2
-
-#ifdef RAPIDJSON_SIMD
-//! Template function specialization for InsituStringStream
-template<> inline void SkipWhitespace(InsituStringStream& is) {
- is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
-}
-
-//! Template function specialization for StringStream
-template<> inline void SkipWhitespace(StringStream& is) {
- is.src_ = SkipWhitespace_SIMD(is.src_);
-}
-
-template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
- is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
-}
-#endif // RAPIDJSON_SIMD
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericReader
-
-//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
-/*! GenericReader parses JSON text from a stream, and send events synchronously to an
- object implementing Handler concept.
-
- It needs to allocate a stack for storing a single decoded string during
- non-destructive parsing.
-
- For in-situ parsing, the decoded string is directly written to the source
- text string, no temporary buffer is required.
-
- A GenericReader object can be reused for parsing multiple JSON text.
-
- \tparam SourceEncoding Encoding of the input stream.
- \tparam TargetEncoding Encoding of the parse output.
- \tparam StackAllocator Allocator type for stack.
-*/
-template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
-class GenericReader {
-public:
- typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
-
- //! Constructor.
- /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
- \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
- */
- GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
-
- //! Parse JSON text.
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \tparam InputStream Type of input stream, implementing Stream concept.
- \tparam Handler Type of handler, implementing Handler concept.
- \param is Input stream to be parsed.
- \param handler The handler to receive events.
- \return Whether the parsing is successful.
- */
- template <unsigned parseFlags, typename InputStream, typename Handler>
- ParseResult Parse(InputStream& is, Handler& handler) {
- if (parseFlags & kParseIterativeFlag)
- return IterativeParse<parseFlags>(is, handler);
-
- parseResult_.Clear();
-
- ClearStackOnExit scope(*this);
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
-
- if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- }
- else {
- ParseValue<parseFlags>(is, handler);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
-
- if (!(parseFlags & kParseStopWhenDoneFlag)) {
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
-
- if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- }
- }
- }
-
- return parseResult_;
- }
-
- //! Parse JSON text (with \ref kParseDefaultFlags)
- /*! \tparam InputStream Type of input stream, implementing Stream concept
- \tparam Handler Type of handler, implementing Handler concept.
- \param is Input stream to be parsed.
- \param handler The handler to receive events.
- \return Whether the parsing is successful.
- */
- template <typename InputStream, typename Handler>
- ParseResult Parse(InputStream& is, Handler& handler) {
- return Parse<kParseDefaultFlags>(is, handler);
- }
-
- //! Whether a parse error has occured in the last parsing.
- bool HasParseError() const { return parseResult_.IsError(); }
-
- //! Get the \ref ParseErrorCode of last parsing.
- ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
-
- //! Get the position of last parsing error in input, 0 otherwise.
- size_t GetErrorOffset() const { return parseResult_.Offset(); }
-
-protected:
- void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
-
-private:
- // Prohibit copy constructor & assignment operator.
- GenericReader(const GenericReader&);
- GenericReader& operator=(const GenericReader&);
-
- void ClearStack() { stack_.Clear(); }
-
- // clear stack on any exit from ParseStream, e.g. due to exception
- struct ClearStackOnExit {
- explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
- ~ClearStackOnExit() { r_.ClearStack(); }
- private:
- GenericReader& r_;
- ClearStackOnExit(const ClearStackOnExit&);
- ClearStackOnExit& operator=(const ClearStackOnExit&);
- };
-
- template<unsigned parseFlags, typename InputStream>
- void SkipWhitespaceAndComments(InputStream& is) {
- SkipWhitespace(is);
-
- if (parseFlags & kParseCommentsFlag) {
- while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) {
- if (Consume(is, '*')) {
- while (true) {
- if (RAPIDJSON_UNLIKELY(is.Peek() == '\0'))
- RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
- else if (Consume(is, '*')) {
- if (Consume(is, '/'))
- break;
- }
- else
- is.Take();
- }
- }
- else if (RAPIDJSON_LIKELY(Consume(is, '/')))
- while (is.Peek() != '\0' && is.Take() != '\n');
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
-
- SkipWhitespace(is);
- }
- }
- }
-
- // Parse object: { string : value, ... }
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseObject(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == '{');
- is.Take(); // Skip '{'
-
- if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- if (Consume(is, '}')) {
- if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- }
-
- for (SizeType memberCount = 0;;) {
- if (RAPIDJSON_UNLIKELY(is.Peek() != '"'))
- RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
-
- ParseString<parseFlags>(is, handler, true);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- if (RAPIDJSON_UNLIKELY(!Consume(is, ':')))
- RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- ParseValue<parseFlags>(is, handler);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- ++memberCount;
-
- switch (is.Peek()) {
- case ',':
- is.Take();
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- break;
- case '}':
- is.Take();
- if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- default:
- RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy
- }
-
- if (parseFlags & kParseTrailingCommasFlag) {
- if (is.Peek() == '}') {
- if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- is.Take();
- return;
- }
- }
- }
- }
-
- // Parse array: [ value, ... ]
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseArray(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == '[');
- is.Take(); // Skip '['
-
- if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- if (Consume(is, ']')) {
- if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- }
-
- for (SizeType elementCount = 0;;) {
- ParseValue<parseFlags>(is, handler);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- ++elementCount;
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- if (Consume(is, ',')) {
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- }
- else if (Consume(is, ']')) {
- if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
-
- if (parseFlags & kParseTrailingCommasFlag) {
- if (is.Peek() == ']') {
- if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- is.Take();
- return;
- }
- }
- }
- }
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseNull(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == 'n');
- is.Take();
-
- if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) {
- if (RAPIDJSON_UNLIKELY(!handler.Null()))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
- }
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseTrue(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == 't');
- is.Take();
-
- if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) {
- if (RAPIDJSON_UNLIKELY(!handler.Bool(true)))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
- }
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseFalse(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == 'f');
- is.Take();
-
- if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) {
- if (RAPIDJSON_UNLIKELY(!handler.Bool(false)))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell());
- }
-
- template<typename InputStream>
- RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) {
- if (RAPIDJSON_LIKELY(is.Peek() == expect)) {
- is.Take();
- return true;
- }
- else
- return false;
- }
-
- // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
- template<typename InputStream>
- unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
- unsigned codepoint = 0;
- for (int i = 0; i < 4; i++) {
- Ch c = is.Peek();
- codepoint <<= 4;
- codepoint += static_cast<unsigned>(c);
- if (c >= '0' && c <= '9')
- codepoint -= '0';
- else if (c >= 'A' && c <= 'F')
- codepoint -= 'A' - 10;
- else if (c >= 'a' && c <= 'f')
- codepoint -= 'a' - 10;
- else {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
- }
- is.Take();
- }
- return codepoint;
- }
-
- template <typename CharType>
- class StackStream {
- public:
- typedef CharType Ch;
-
- StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
- RAPIDJSON_FORCEINLINE void Put(Ch c) {
- *stack_.template Push<Ch>() = c;
- ++length_;
- }
-
- RAPIDJSON_FORCEINLINE void* Push(SizeType count) {
- length_ += count;
- return stack_.template Push<Ch>(count);
- }
-
- size_t Length() const { return length_; }
-
- Ch* Pop() {
- return stack_.template Pop<Ch>(length_);
- }
-
- private:
- StackStream(const StackStream&);
- StackStream& operator=(const StackStream&);
-
- internal::Stack<StackAllocator>& stack_;
- SizeType length_;
- };
-
- // Parse string and generate String event. Different code paths for kParseInsituFlag.
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
- internal::StreamLocalCopy<InputStream> copy(is);
- InputStream& s(copy.s);
-
- RAPIDJSON_ASSERT(s.Peek() == '\"');
- s.Take(); // Skip '\"'
-
- bool success = false;
- if (parseFlags & kParseInsituFlag) {
- typename InputStream::Ch *head = s.PutBegin();
- ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- size_t length = s.PutEnd(head) - 1;
- RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
- const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
- success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
- }
- else {
- StackStream<typename TargetEncoding::Ch> stackStream(stack_);
- ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
- const typename TargetEncoding::Ch* const str = stackStream.Pop();
- success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
- }
- if (RAPIDJSON_UNLIKELY(!success))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
- }
-
- // Parse string to an output is
- // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
- template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- static const char escape[256] = {
- Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
- Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
- 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
- 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
- };
-#undef Z16
-//!@endcond
-
- for (;;) {
- // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation.
- if (!(parseFlags & kParseValidateEncodingFlag))
- ScanCopyUnescapedString(is, os);
-
- Ch c = is.Peek();
- if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
- size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
- is.Take();
- Ch e = is.Peek();
- if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
- is.Take();
- os.Put(static_cast<typename TEncoding::Ch>(escape[static_cast<unsigned char>(e)]));
- }
- else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode
- is.Take();
- unsigned codepoint = ParseHex4(is, escapeOffset);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) {
- // Handle UTF-16 surrogate pair
- if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u')))
- RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
- unsigned codepoint2 = ParseHex4(is, escapeOffset);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF))
- RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset);
- codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
- }
- TEncoding::Encode(os, codepoint);
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset);
- }
- else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote
- is.Take();
- os.Put('\0'); // null-terminate the string
- return;
- }
- else if (RAPIDJSON_UNLIKELY(static_cast<unsigned>(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
- if (c == '\0')
- RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
- }
- else {
- size_t offset = is.Tell();
- if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ?
- !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
- !Transcoder<SEncoding, TEncoding>::Transcode(is, os))))
- RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset);
- }
- }
- }
-
- template<typename InputStream, typename OutputStream>
- static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) {
- // Do nothing for generic version
- }
-
-#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
- // StringStream -> StackStream<char>
- static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
- const char* p = is.src_;
-
- // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
- while (p != nextAligned)
- if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
- is.src_ = p;
- return;
- }
- else
- os.Put(*p++);
-
- // The rest of string using SIMD
- static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
- static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
- static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
- const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
- const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
- const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
-
- for (;; p += 16) {
- const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
- const __m128i t1 = _mm_cmpeq_epi8(s, dq);
- const __m128i t2 = _mm_cmpeq_epi8(s, bs);
- const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
- const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
- unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
- if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
- SizeType length;
- #ifdef _MSC_VER // Find the index of first escaped
- unsigned long offset;
- _BitScanForward(&offset, r);
- length = offset;
- #else
- length = static_cast<SizeType>(__builtin_ffs(r) - 1);
- #endif
- char* q = reinterpret_cast<char*>(os.Push(length));
- for (size_t i = 0; i < length; i++)
- q[i] = p[i];
-
- p += length;
- break;
- }
- _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
- }
-
- is.src_ = p;
- }
-
- // InsituStringStream -> InsituStringStream
- static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
- RAPIDJSON_ASSERT(&is == &os);
- (void)os;
-
- if (is.src_ == is.dst_) {
- SkipUnescapedString(is);
- return;
- }
-
- char* p = is.src_;
- char *q = is.dst_;
-
- // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
- while (p != nextAligned)
- if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
- is.src_ = p;
- is.dst_ = q;
- return;
- }
- else
- *q++ = *p++;
-
- // The rest of string using SIMD
- static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
- static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
- static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
- const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
- const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
- const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
-
- for (;; p += 16, q += 16) {
- const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
- const __m128i t1 = _mm_cmpeq_epi8(s, dq);
- const __m128i t2 = _mm_cmpeq_epi8(s, bs);
- const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
- const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
- unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
- if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
- size_t length;
-#ifdef _MSC_VER // Find the index of first escaped
- unsigned long offset;
- _BitScanForward(&offset, r);
- length = offset;
-#else
- length = static_cast<size_t>(__builtin_ffs(r) - 1);
-#endif
- for (const char* pend = p + length; p != pend; )
- *q++ = *p++;
- break;
- }
- _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s);
- }
-
- is.src_ = p;
- is.dst_ = q;
- }
-
- // When read/write pointers are the same for insitu stream, just skip unescaped characters
- static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
- RAPIDJSON_ASSERT(is.src_ == is.dst_);
- char* p = is.src_;
-
- // Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
- for (; p != nextAligned; p++)
- if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
- is.src_ = is.dst_ = p;
- return;
- }
-
- // The rest of string using SIMD
- static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
- static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
- static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
- const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
- const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
- const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
-
- for (;; p += 16) {
- const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
- const __m128i t1 = _mm_cmpeq_epi8(s, dq);
- const __m128i t2 = _mm_cmpeq_epi8(s, bs);
- const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
- const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
- unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
- if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
- size_t length;
-#ifdef _MSC_VER // Find the index of first escaped
- unsigned long offset;
- _BitScanForward(&offset, r);
- length = offset;
-#else
- length = static_cast<size_t>(__builtin_ffs(r) - 1);
-#endif
- p += length;
- break;
- }
- }
-
- is.src_ = is.dst_ = p;
- }
-#endif
-
- template<typename InputStream, bool backup, bool pushOnTake>
- class NumberStream;
-
- template<typename InputStream>
- class NumberStream<InputStream, false, false> {
- public:
- typedef typename InputStream::Ch Ch;
-
- NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
- ~NumberStream() {}
-
- RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
- RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
- RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
- RAPIDJSON_FORCEINLINE void Push(char) {}
-
- size_t Tell() { return is.Tell(); }
- size_t Length() { return 0; }
- const char* Pop() { return 0; }
-
- protected:
- NumberStream& operator=(const NumberStream&);
-
- InputStream& is;
- };
-
- template<typename InputStream>
- class NumberStream<InputStream, true, false> : public NumberStream<InputStream, false, false> {
- typedef NumberStream<InputStream, false, false> Base;
- public:
- NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {}
- ~NumberStream() {}
-
- RAPIDJSON_FORCEINLINE Ch TakePush() {
- stackStream.Put(static_cast<char>(Base::is.Peek()));
- return Base::is.Take();
- }
-
- RAPIDJSON_FORCEINLINE void Push(char c) {
- stackStream.Put(c);
- }
-
- size_t Length() { return stackStream.Length(); }
-
- const char* Pop() {
- stackStream.Put('\0');
- return stackStream.Pop();
- }
-
- private:
- StackStream<char> stackStream;
- };
-
- template<typename InputStream>
- class NumberStream<InputStream, true, true> : public NumberStream<InputStream, true, false> {
- typedef NumberStream<InputStream, true, false> Base;
- public:
- NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
- ~NumberStream() {}
-
- RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
- };
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseNumber(InputStream& is, Handler& handler) {
- internal::StreamLocalCopy<InputStream> copy(is);
- NumberStream<InputStream,
- ((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
- ((parseFlags & kParseInsituFlag) == 0) :
- ((parseFlags & kParseFullPrecisionFlag) != 0),
- (parseFlags & kParseNumbersAsStringsFlag) != 0 &&
- (parseFlags & kParseInsituFlag) == 0> s(*this, copy.s);
-
- size_t startOffset = s.Tell();
- double d = 0.0;
- bool useNanOrInf = false;
-
- // Parse minus
- bool minus = Consume(s, '-');
-
- // Parse int: zero / ( digit1-9 *DIGIT )
- unsigned i = 0;
- uint64_t i64 = 0;
- bool use64bit = false;
- int significandDigit = 0;
- if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) {
- i = 0;
- s.TakePush();
- }
- else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) {
- i = static_cast<unsigned>(s.TakePush() - '0');
-
- if (minus)
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648
- if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) {
- i64 = i;
- use64bit = true;
- break;
- }
- }
- i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- else
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295
- if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) {
- i64 = i;
- use64bit = true;
- break;
- }
- }
- i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- }
- // Parse NaN or Infinity here
- else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
- useNanOrInf = true;
- if (RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
- d = std::numeric_limits<double>::quiet_NaN();
- }
- else if (RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
- d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
- if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
- && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
-
- // Parse 64bit int
- bool useDouble = false;
- if (use64bit) {
- if (minus)
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808
- if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) {
- d = static_cast<double>(i64);
- useDouble = true;
- break;
- }
- i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- else
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615
- if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) {
- d = static_cast<double>(i64);
- useDouble = true;
- break;
- }
- i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- }
-
- // Force double for big integer
- if (useDouble) {
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
- d = d * 10 + (s.TakePush() - '0');
- }
- }
-
- // Parse frac = decimal-point 1*DIGIT
- int expFrac = 0;
- size_t decimalPosition;
- if (Consume(s, '.')) {
- decimalPosition = s.Length();
-
- if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
-
- if (!useDouble) {
-#if RAPIDJSON_64BIT
- // Use i64 to store significand in 64-bit architecture
- if (!use64bit)
- i64 = i;
-
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
- break;
- else {
- i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
- --expFrac;
- if (i64 != 0)
- significandDigit++;
- }
- }
-
- d = static_cast<double>(i64);
-#else
- // Use double to store significand in 32-bit architecture
- d = static_cast<double>(use64bit ? i64 : i);
-#endif
- useDouble = true;
- }
-
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- if (significandDigit < 17) {
- d = d * 10.0 + (s.TakePush() - '0');
- --expFrac;
- if (RAPIDJSON_LIKELY(d > 0.0))
- significandDigit++;
- }
- else
- s.TakePush();
- }
- }
- else
- decimalPosition = s.Length(); // decimal position at the end of integer.
-
- // Parse exp = e [ minus / plus ] 1*DIGIT
- int exp = 0;
- if (Consume(s, 'e') || Consume(s, 'E')) {
- if (!useDouble) {
- d = static_cast<double>(use64bit ? i64 : i);
- useDouble = true;
- }
-
- bool expMinus = false;
- if (Consume(s, '+'))
- ;
- else if (Consume(s, '-'))
- expMinus = true;
-
- if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- exp = static_cast<int>(s.Take() - '0');
- if (expMinus) {
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- exp = exp * 10 + static_cast<int>(s.Take() - '0');
- if (exp >= 214748364) { // Issue #313: prevent overflow exponent
- while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
- s.Take();
- }
- }
- }
- else { // positive exp
- int maxExp = 308 - expFrac;
- while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
- exp = exp * 10 + static_cast<int>(s.Take() - '0');
- if (RAPIDJSON_UNLIKELY(exp > maxExp))
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
- }
- }
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
-
- if (expMinus)
- exp = -exp;
- }
-
- // Finish parsing, call event according to the type of number.
- bool cont = true;
-
- if (parseFlags & kParseNumbersAsStringsFlag) {
- if (parseFlags & kParseInsituFlag) {
- s.Pop(); // Pop stack no matter if it will be used or not.
- typename InputStream::Ch* head = is.PutBegin();
- const size_t length = s.Tell() - startOffset;
- RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
- // unable to insert the \0 character here, it will erase the comma after this number
- const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
- cont = handler.RawNumber(str, SizeType(length), false);
- }
- else {
- SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
- StringStream srcStream(s.Pop());
- StackStream<typename TargetEncoding::Ch> dstStream(stack_);
- while (numCharsToCopy--) {
- Transcoder<UTF8<>, TargetEncoding>::Transcode(srcStream, dstStream);
- }
- dstStream.Put('\0');
- const typename TargetEncoding::Ch* str = dstStream.Pop();
- const SizeType length = static_cast<SizeType>(dstStream.Length()) - 1;
- cont = handler.RawNumber(str, SizeType(length), true);
- }
- }
- else {
- size_t length = s.Length();
- const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
-
- if (useDouble) {
- int p = exp + expFrac;
- if (parseFlags & kParseFullPrecisionFlag)
- d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
- else
- d = internal::StrtodNormalPrecision(d, p);
-
- cont = handler.Double(minus ? -d : d);
- }
- else if (useNanOrInf) {
- cont = handler.Double(d);
- }
- else {
- if (use64bit) {
- if (minus)
- cont = handler.Int64(static_cast<int64_t>(~i64 + 1));
- else
- cont = handler.Uint64(i64);
- }
- else {
- if (minus)
- cont = handler.Int(static_cast<int32_t>(~i + 1));
- else
- cont = handler.Uint(i);
- }
- }
- }
- if (RAPIDJSON_UNLIKELY(!cont))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
- }
-
- // Parse any JSON value
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseValue(InputStream& is, Handler& handler) {
- switch (is.Peek()) {
- case 'n': ParseNull <parseFlags>(is, handler); break;
- case 't': ParseTrue <parseFlags>(is, handler); break;
- case 'f': ParseFalse <parseFlags>(is, handler); break;
- case '"': ParseString<parseFlags>(is, handler); break;
- case '{': ParseObject<parseFlags>(is, handler); break;
- case '[': ParseArray <parseFlags>(is, handler); break;
- default :
- ParseNumber<parseFlags>(is, handler);
- break;
-
- }
- }
-
- // Iterative Parsing
-
- // States
- enum IterativeParsingState {
- IterativeParsingStartState = 0,
- IterativeParsingFinishState,
- IterativeParsingErrorState,
-
- // Object states
- IterativeParsingObjectInitialState,
- IterativeParsingMemberKeyState,
- IterativeParsingKeyValueDelimiterState,
- IterativeParsingMemberValueState,
- IterativeParsingMemberDelimiterState,
- IterativeParsingObjectFinishState,
-
- // Array states
- IterativeParsingArrayInitialState,
- IterativeParsingElementState,
- IterativeParsingElementDelimiterState,
- IterativeParsingArrayFinishState,
-
- // Single value state
- IterativeParsingValueState
- };
-
- enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
-
- // Tokens
- enum Token {
- LeftBracketToken = 0,
- RightBracketToken,
-
- LeftCurlyBracketToken,
- RightCurlyBracketToken,
-
- CommaToken,
- ColonToken,
-
- StringToken,
- FalseToken,
- TrueToken,
- NullToken,
- NumberToken,
-
- kTokenCount
- };
-
- RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#define N NumberToken
-#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
- // Maps from ASCII to Token
- static const unsigned char tokenMap[256] = {
- N16, // 00~0F
- N16, // 10~1F
- N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
- N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
- N16, // 40~4F
- N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
- N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
- N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
- N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
- };
-#undef N
-#undef N16
-//!@endcond
-
- if (sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256)
- return static_cast<Token>(tokenMap[static_cast<unsigned char>(c)]);
- else
- return NumberToken;
- }
-
- RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
- // current state x one lookahead token -> new state
- static const char G[cIterativeParsingStateCount][kTokenCount] = {
- // Start
- {
- IterativeParsingArrayInitialState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingValueState, // String
- IterativeParsingValueState, // False
- IterativeParsingValueState, // True
- IterativeParsingValueState, // Null
- IterativeParsingValueState // Number
- },
- // Finish(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // Error(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // ObjectInitial
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingObjectFinishState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingMemberKeyState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // MemberKey
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingKeyValueDelimiterState, // Colon
- IterativeParsingErrorState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // KeyValueDelimiter
- {
- IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
- IterativeParsingErrorState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingMemberValueState, // String
- IterativeParsingMemberValueState, // False
- IterativeParsingMemberValueState, // True
- IterativeParsingMemberValueState, // Null
- IterativeParsingMemberValueState // Number
- },
- // MemberValue
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingObjectFinishState, // Right curly bracket
- IterativeParsingMemberDelimiterState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingErrorState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // MemberDelimiter
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingObjectFinishState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingMemberKeyState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // ObjectFinish(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // ArrayInitial
- {
- IterativeParsingArrayInitialState, // Left bracket(push Element state)
- IterativeParsingArrayFinishState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingElementState, // String
- IterativeParsingElementState, // False
- IterativeParsingElementState, // True
- IterativeParsingElementState, // Null
- IterativeParsingElementState // Number
- },
- // Element
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingArrayFinishState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingElementDelimiterState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingErrorState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // ElementDelimiter
- {
- IterativeParsingArrayInitialState, // Left bracket(push Element state)
- IterativeParsingArrayFinishState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingElementState, // String
- IterativeParsingElementState, // False
- IterativeParsingElementState, // True
- IterativeParsingElementState, // Null
- IterativeParsingElementState // Number
- },
- // ArrayFinish(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // Single Value (sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- }
- }; // End of G
-
- return static_cast<IterativeParsingState>(G[state][token]);
- }
-
- // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
- // May return a new state on state pop.
- template <unsigned parseFlags, typename InputStream, typename Handler>
- RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
- (void)token;
-
- switch (dst) {
- case IterativeParsingErrorState:
- return dst;
-
- case IterativeParsingObjectInitialState:
- case IterativeParsingArrayInitialState:
- {
- // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
- // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
- IterativeParsingState n = src;
- if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
- n = IterativeParsingElementState;
- else if (src == IterativeParsingKeyValueDelimiterState)
- n = IterativeParsingMemberValueState;
- // Push current state.
- *stack_.template Push<SizeType>(1) = n;
- // Initialize and push the member/element count.
- *stack_.template Push<SizeType>(1) = 0;
- // Call handler
- bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
- // On handler short circuits the parsing.
- if (!hr) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
- return IterativeParsingErrorState;
- }
- else {
- is.Take();
- return dst;
- }
- }
-
- case IterativeParsingMemberKeyState:
- ParseString<parseFlags>(is, handler, true);
- if (HasParseError())
- return IterativeParsingErrorState;
- else
- return dst;
-
- case IterativeParsingKeyValueDelimiterState:
- RAPIDJSON_ASSERT(token == ColonToken);
- is.Take();
- return dst;
-
- case IterativeParsingMemberValueState:
- // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
- ParseValue<parseFlags>(is, handler);
- if (HasParseError()) {
- return IterativeParsingErrorState;
- }
- return dst;
-
- case IterativeParsingElementState:
- // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
- ParseValue<parseFlags>(is, handler);
- if (HasParseError()) {
- return IterativeParsingErrorState;
- }
- return dst;
-
- case IterativeParsingMemberDelimiterState:
- case IterativeParsingElementDelimiterState:
- is.Take();
- // Update member/element count.
- *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
- return dst;
-
- case IterativeParsingObjectFinishState:
- {
- // Transit from delimiter is only allowed when trailing commas are enabled
- if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell());
- return IterativeParsingErrorState;
- }
- // Get member count.
- SizeType c = *stack_.template Pop<SizeType>(1);
- // If the object is not empty, count the last member.
- if (src == IterativeParsingMemberValueState)
- ++c;
- // Restore the state.
- IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
- // Transit to Finish state if this is the topmost scope.
- if (n == IterativeParsingStartState)
- n = IterativeParsingFinishState;
- // Call handler
- bool hr = handler.EndObject(c);
- // On handler short circuits the parsing.
- if (!hr) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
- return IterativeParsingErrorState;
- }
- else {
- is.Take();
- return n;
- }
- }
-
- case IterativeParsingArrayFinishState:
- {
- // Transit from delimiter is only allowed when trailing commas are enabled
- if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell());
- return IterativeParsingErrorState;
- }
- // Get element count.
- SizeType c = *stack_.template Pop<SizeType>(1);
- // If the array is not empty, count the last element.
- if (src == IterativeParsingElementState)
- ++c;
- // Restore the state.
- IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
- // Transit to Finish state if this is the topmost scope.
- if (n == IterativeParsingStartState)
- n = IterativeParsingFinishState;
- // Call handler
- bool hr = handler.EndArray(c);
- // On handler short circuits the parsing.
- if (!hr) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
- return IterativeParsingErrorState;
- }
- else {
- is.Take();
- return n;
- }
- }
-
- default:
- // This branch is for IterativeParsingValueState actually.
- // Use `default:` rather than
- // `case IterativeParsingValueState:` is for code coverage.
-
- // The IterativeParsingStartState is not enumerated in this switch-case.
- // It is impossible for that case. And it can be caught by following assertion.
-
- // The IterativeParsingFinishState is not enumerated in this switch-case either.
- // It is a "derivative" state which cannot triggered from Predict() directly.
- // Therefore it cannot happen here. And it can be caught by following assertion.
- RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
-
- // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
- ParseValue<parseFlags>(is, handler);
- if (HasParseError()) {
- return IterativeParsingErrorState;
- }
- return IterativeParsingFinishState;
- }
- }
-
- template <typename InputStream>
- void HandleError(IterativeParsingState src, InputStream& is) {
- if (HasParseError()) {
- // Error flag has been set.
- return;
- }
-
- switch (src) {
- case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return;
- case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return;
- case IterativeParsingObjectInitialState:
- case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return;
- case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return;
- case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return;
- case IterativeParsingKeyValueDelimiterState:
- case IterativeParsingArrayInitialState:
- case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return;
- default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return;
- }
- }
-
- template <unsigned parseFlags, typename InputStream, typename Handler>
- ParseResult IterativeParse(InputStream& is, Handler& handler) {
- parseResult_.Clear();
- ClearStackOnExit scope(*this);
- IterativeParsingState state = IterativeParsingStartState;
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- while (is.Peek() != '\0') {
- Token t = Tokenize(is.Peek());
- IterativeParsingState n = Predict(state, t);
- IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
-
- if (d == IterativeParsingErrorState) {
- HandleError(state, is);
- break;
- }
-
- state = d;
-
- // Do not further consume streams if a root JSON has been parsed.
- if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
- break;
-
- SkipWhitespaceAndComments<parseFlags>(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- }
-
- // Handle the end of file.
- if (state != IterativeParsingFinishState)
- HandleError(state, is);
-
- return parseResult_;
- }
-
- static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
- internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
- ParseResult parseResult_;
-}; // class GenericReader
-
-//! Reader with UTF8 encoding and default allocator.
-typedef GenericReader<UTF8<>, UTF8<> > Reader;
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_READER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available->
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License-> You may obtain a copy of the License at
-//
-// http://opensource->org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied-> See the License for the
-// specific language governing permissions and limitations under the License->
-
-#ifndef RAPIDJSON_SCHEMA_H_
-#define RAPIDJSON_SCHEMA_H_
-
-#include "document.h"
-#include "pointer.h"
-#include <cmath> // abs, floor
-
-#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
-#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
-#else
-#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
-#endif
-
-#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
-#define RAPIDJSON_SCHEMA_USE_STDREGEX 1
-#else
-#define RAPIDJSON_SCHEMA_USE_STDREGEX 0
-#endif
-
-#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
-#include "internal/regex.h"
-#elif RAPIDJSON_SCHEMA_USE_STDREGEX
-#include <regex>
-#endif
-
-#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX
-#define RAPIDJSON_SCHEMA_HAS_REGEX 1
-#else
-#define RAPIDJSON_SCHEMA_HAS_REGEX 0
-#endif
-
-#ifndef RAPIDJSON_SCHEMA_VERBOSE
-#define RAPIDJSON_SCHEMA_VERBOSE 0
-#endif
-
-#if RAPIDJSON_SCHEMA_VERBOSE
-#include "stringbuffer.h"
-#endif
-
-RAPIDJSON_DIAG_PUSH
-
-#if defined(__GNUC__)
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_OFF(weak-vtables)
-RAPIDJSON_DIAG_OFF(exit-time-destructors)
-RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
-RAPIDJSON_DIAG_OFF(variadic-macros)
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Verbose Utilities
-
-#if RAPIDJSON_SCHEMA_VERBOSE
-
-namespace internal {
-
-inline void PrintInvalidKeyword(const char* keyword) {
- printf("Fail keyword: %s\n", keyword);
-}
-
-inline void PrintInvalidKeyword(const wchar_t* keyword) {
- wprintf(L"Fail keyword: %ls\n", keyword);
-}
-
-inline void PrintInvalidDocument(const char* document) {
- printf("Fail document: %s\n\n", document);
-}
-
-inline void PrintInvalidDocument(const wchar_t* document) {
- wprintf(L"Fail document: %ls\n\n", document);
-}
-
-inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
- printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
-}
-
-inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
- wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
-}
-
-} // namespace internal
-
-#endif // RAPIDJSON_SCHEMA_VERBOSE
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_INVALID_KEYWORD_RETURN
-
-#if RAPIDJSON_SCHEMA_VERBOSE
-#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
-#else
-#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
-#endif
-
-#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
-RAPIDJSON_MULTILINEMACRO_BEGIN\
- context.invalidKeyword = keyword.GetString();\
- RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
- return false;\
-RAPIDJSON_MULTILINEMACRO_END
-
-///////////////////////////////////////////////////////////////////////////////
-// Forward declarations
-
-template <typename ValueType, typename Allocator>
-class GenericSchemaDocument;
-
-namespace internal {
-
-template <typename SchemaDocumentType>
-class Schema;
-
-///////////////////////////////////////////////////////////////////////////////
-// ISchemaValidator
-
-class ISchemaValidator {
-public:
- virtual ~ISchemaValidator() {}
- virtual bool IsValid() const = 0;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// ISchemaStateFactory
-
-template <typename SchemaType>
-class ISchemaStateFactory {
-public:
- virtual ~ISchemaStateFactory() {}
- virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
- virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
- virtual void* CreateHasher() = 0;
- virtual uint64_t GetHashCode(void* hasher) = 0;
- virtual void DestroryHasher(void* hasher) = 0;
- virtual void* MallocState(size_t size) = 0;
- virtual void FreeState(void* p) = 0;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Hasher
-
-// For comparison of compound value
-template<typename Encoding, typename Allocator>
-class Hasher {
-public:
- typedef typename Encoding::Ch Ch;
-
- Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
-
- bool Null() { return WriteType(kNullType); }
- bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
- bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
- bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
- bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
- bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
- bool Double(double d) {
- Number n;
- if (d < 0) n.u.i = static_cast<int64_t>(d);
- else n.u.u = static_cast<uint64_t>(d);
- n.d = d;
- return WriteNumber(n);
- }
-
- bool RawNumber(const Ch* str, SizeType len, bool) {
- WriteBuffer(kNumberType, str, len * sizeof(Ch));
- return true;
- }
-
- bool String(const Ch* str, SizeType len, bool) {
- WriteBuffer(kStringType, str, len * sizeof(Ch));
- return true;
- }
-
- bool StartObject() { return true; }
- bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
- bool EndObject(SizeType memberCount) {
- uint64_t h = Hash(0, kObjectType);
- uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
- for (SizeType i = 0; i < memberCount; i++)
- h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
- *stack_.template Push<uint64_t>() = h;
- return true;
- }
-
- bool StartArray() { return true; }
- bool EndArray(SizeType elementCount) {
- uint64_t h = Hash(0, kArrayType);
- uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
- for (SizeType i = 0; i < elementCount; i++)
- h = Hash(h, e[i]); // Use hash to achieve element order sensitive
- *stack_.template Push<uint64_t>() = h;
- return true;
- }
-
- bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
-
- uint64_t GetHashCode() const {
- RAPIDJSON_ASSERT(IsValid());
- return *stack_.template Top<uint64_t>();
- }
-
-private:
- static const size_t kDefaultSize = 256;
- struct Number {
- union U {
- uint64_t u;
- int64_t i;
- }u;
- double d;
- };
-
- bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
-
- bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
-
- bool WriteBuffer(Type type, const void* data, size_t len) {
- // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
- uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
- const unsigned char* d = static_cast<const unsigned char*>(data);
- for (size_t i = 0; i < len; i++)
- h = Hash(h, d[i]);
- *stack_.template Push<uint64_t>() = h;
- return true;
- }
-
- static uint64_t Hash(uint64_t h, uint64_t d) {
- static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
- h ^= d;
- h *= kPrime;
- return h;
- }
-
- Stack<Allocator> stack_;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// SchemaValidationContext
-
-template <typename SchemaDocumentType>
-struct SchemaValidationContext {
- typedef Schema<SchemaDocumentType> SchemaType;
- typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
- typedef typename SchemaType::ValueType ValueType;
- typedef typename ValueType::Ch Ch;
-
- enum PatternValidatorType {
- kPatternValidatorOnly,
- kPatternValidatorWithProperty,
- kPatternValidatorWithAdditionalProperty
- };
-
- SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) :
- factory(f),
- schema(s),
- valueSchema(),
- invalidKeyword(),
- hasher(),
- arrayElementHashCodes(),
- validators(),
- validatorCount(),
- patternPropertiesValidators(),
- patternPropertiesValidatorCount(),
- patternPropertiesSchemas(),
- patternPropertiesSchemaCount(),
- valuePatternValidatorType(kPatternValidatorOnly),
- propertyExist(),
- inArray(false),
- valueUniqueness(false),
- arrayUniqueness(false)
- {
- }
-
- ~SchemaValidationContext() {
- if (hasher)
- factory.DestroryHasher(hasher);
- if (validators) {
- for (SizeType i = 0; i < validatorCount; i++)
- factory.DestroySchemaValidator(validators[i]);
- factory.FreeState(validators);
- }
- if (patternPropertiesValidators) {
- for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
- factory.DestroySchemaValidator(patternPropertiesValidators[i]);
- factory.FreeState(patternPropertiesValidators);
- }
- if (patternPropertiesSchemas)
- factory.FreeState(patternPropertiesSchemas);
- if (propertyExist)
- factory.FreeState(propertyExist);
- }
-
- SchemaValidatorFactoryType& factory;
- const SchemaType* schema;
- const SchemaType* valueSchema;
- const Ch* invalidKeyword;
- void* hasher; // Only validator access
- void* arrayElementHashCodes; // Only validator access this
- ISchemaValidator** validators;
- SizeType validatorCount;
- ISchemaValidator** patternPropertiesValidators;
- SizeType patternPropertiesValidatorCount;
- const SchemaType** patternPropertiesSchemas;
- SizeType patternPropertiesSchemaCount;
- PatternValidatorType valuePatternValidatorType;
- PatternValidatorType objectPatternValidatorType;
- SizeType arrayElementIndex;
- bool* propertyExist;
- bool inArray;
- bool valueUniqueness;
- bool arrayUniqueness;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Schema
-
-template <typename SchemaDocumentType>
-class Schema {
-public:
- typedef typename SchemaDocumentType::ValueType ValueType;
- typedef typename SchemaDocumentType::AllocatorType AllocatorType;
- typedef typename SchemaDocumentType::PointerType PointerType;
- typedef typename ValueType::EncodingType EncodingType;
- typedef typename EncodingType::Ch Ch;
- typedef SchemaValidationContext<SchemaDocumentType> Context;
- typedef Schema<SchemaDocumentType> SchemaType;
- typedef GenericValue<EncodingType, AllocatorType> SValue;
- friend class GenericSchemaDocument<ValueType, AllocatorType>;
-
- Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
- allocator_(allocator),
- enum_(),
- enumCount_(),
- not_(),
- type_((1 << kTotalSchemaType) - 1), // typeless
- validatorCount_(),
- properties_(),
- additionalPropertiesSchema_(),
- patternProperties_(),
- patternPropertyCount_(),
- propertyCount_(),
- minProperties_(),
- maxProperties_(SizeType(~0)),
- additionalProperties_(true),
- hasDependencies_(),
- hasRequired_(),
- hasSchemaDependencies_(),
- additionalItemsSchema_(),
- itemsList_(),
- itemsTuple_(),
- itemsTupleCount_(),
- minItems_(),
- maxItems_(SizeType(~0)),
- additionalItems_(true),
- uniqueItems_(false),
- pattern_(),
- minLength_(0),
- maxLength_(~SizeType(0)),
- exclusiveMinimum_(false),
- exclusiveMaximum_(false)
- {
- typedef typename SchemaDocumentType::ValueType ValueType;
- typedef typename ValueType::ConstValueIterator ConstValueIterator;
- typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
-
- if (!value.IsObject())
- return;
-
- if (const ValueType* v = GetMember(value, GetTypeString())) {
- type_ = 0;
- if (v->IsString())
- AddType(*v);
- else if (v->IsArray())
- for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
- AddType(*itr);
- }
-
- if (const ValueType* v = GetMember(value, GetEnumString()))
- if (v->IsArray() && v->Size() > 0) {
- enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
- for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
- typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
- char buffer[256 + 24];
- MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
- EnumHasherType h(&hasherAllocator, 256);
- itr->Accept(h);
- enum_[enumCount_++] = h.GetHashCode();
- }
- }
-
- if (schemaDocument) {
- AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
- AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
- AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
- }
-
- if (const ValueType* v = GetMember(value, GetNotString())) {
- schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document);
- notValidatorIndex_ = validatorCount_;
- validatorCount_++;
- }
-
- // Object
-
- const ValueType* properties = GetMember(value, GetPropertiesString());
- const ValueType* required = GetMember(value, GetRequiredString());
- const ValueType* dependencies = GetMember(value, GetDependenciesString());
- {
- // Gather properties from properties/required/dependencies
- SValue allProperties(kArrayType);
-
- if (properties && properties->IsObject())
- for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
- AddUniqueElement(allProperties, itr->name);
-
- if (required && required->IsArray())
- for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
- if (itr->IsString())
- AddUniqueElement(allProperties, *itr);
-
- if (dependencies && dependencies->IsObject())
- for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
- AddUniqueElement(allProperties, itr->name);
- if (itr->value.IsArray())
- for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
- if (i->IsString())
- AddUniqueElement(allProperties, *i);
- }
-
- if (allProperties.Size() > 0) {
- propertyCount_ = allProperties.Size();
- properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
- for (SizeType i = 0; i < propertyCount_; i++) {
- new (&properties_[i]) Property();
- properties_[i].name = allProperties[i];
- properties_[i].schema = GetTypeless();
- }
- }
- }
-
- if (properties && properties->IsObject()) {
- PointerType q = p.Append(GetPropertiesString(), allocator_);
- for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
- SizeType index;
- if (FindPropertyIndex(itr->name, &index))
- schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
- }
- }
-
- if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
- PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
- patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
- patternPropertyCount_ = 0;
-
- for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
- new (&patternProperties_[patternPropertyCount_]) PatternProperty();
- patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
- schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
- patternPropertyCount_++;
- }
- }
-
- if (required && required->IsArray())
- for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
- if (itr->IsString()) {
- SizeType index;
- if (FindPropertyIndex(*itr, &index)) {
- properties_[index].required = true;
- hasRequired_ = true;
- }
- }
-
- if (dependencies && dependencies->IsObject()) {
- PointerType q = p.Append(GetDependenciesString(), allocator_);
- hasDependencies_ = true;
- for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
- SizeType sourceIndex;
- if (FindPropertyIndex(itr->name, &sourceIndex)) {
- if (itr->value.IsArray()) {
- properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
- std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
- for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
- SizeType targetIndex;
- if (FindPropertyIndex(*targetItr, &targetIndex))
- properties_[sourceIndex].dependencies[targetIndex] = true;
- }
- }
- else if (itr->value.IsObject()) {
- hasSchemaDependencies_ = true;
- schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
- properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
- validatorCount_++;
- }
- }
- }
- }
-
- if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
- if (v->IsBool())
- additionalProperties_ = v->GetBool();
- else if (v->IsObject())
- schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
- }
-
- AssignIfExist(minProperties_, value, GetMinPropertiesString());
- AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
-
- // Array
- if (const ValueType* v = GetMember(value, GetItemsString())) {
- PointerType q = p.Append(GetItemsString(), allocator_);
- if (v->IsObject()) // List validation
- schemaDocument->CreateSchema(&itemsList_, q, *v, document);
- else if (v->IsArray()) { // Tuple validation
- itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
- SizeType index = 0;
- for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
- schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
- }
- }
-
- AssignIfExist(minItems_, value, GetMinItemsString());
- AssignIfExist(maxItems_, value, GetMaxItemsString());
-
- if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
- if (v->IsBool())
- additionalItems_ = v->GetBool();
- else if (v->IsObject())
- schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
- }
-
- AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
-
- // String
- AssignIfExist(minLength_, value, GetMinLengthString());
- AssignIfExist(maxLength_, value, GetMaxLengthString());
-
- if (const ValueType* v = GetMember(value, GetPatternString()))
- pattern_ = CreatePattern(*v);
-
- // Number
- if (const ValueType* v = GetMember(value, GetMinimumString()))
- if (v->IsNumber())
- minimum_.CopyFrom(*v, *allocator_);
-
- if (const ValueType* v = GetMember(value, GetMaximumString()))
- if (v->IsNumber())
- maximum_.CopyFrom(*v, *allocator_);
-
- AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
- AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
-
- if (const ValueType* v = GetMember(value, GetMultipleOfString()))
- if (v->IsNumber() && v->GetDouble() > 0.0)
- multipleOf_.CopyFrom(*v, *allocator_);
- }
-
- ~Schema() {
- if (allocator_) {
- allocator_->Free(enum_);
- }
- if (properties_) {
- for (SizeType i = 0; i < propertyCount_; i++)
- properties_[i].~Property();
- AllocatorType::Free(properties_);
- }
- if (patternProperties_) {
- for (SizeType i = 0; i < patternPropertyCount_; i++)
- patternProperties_[i].~PatternProperty();
- AllocatorType::Free(patternProperties_);
- }
- AllocatorType::Free(itemsTuple_);
-#if RAPIDJSON_SCHEMA_HAS_REGEX
- if (pattern_) {
- pattern_->~RegexType();
- allocator_->Free(pattern_);
- }
-#endif
- }
-
- bool BeginValue(Context& context) const {
- if (context.inArray) {
- if (uniqueItems_)
- context.valueUniqueness = true;
-
- if (itemsList_)
- context.valueSchema = itemsList_;
- else if (itemsTuple_) {
- if (context.arrayElementIndex < itemsTupleCount_)
- context.valueSchema = itemsTuple_[context.arrayElementIndex];
- else if (additionalItemsSchema_)
- context.valueSchema = additionalItemsSchema_;
- else if (additionalItems_)
- context.valueSchema = GetTypeless();
- else
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
- }
- else
- context.valueSchema = GetTypeless();
-
- context.arrayElementIndex++;
- }
- return true;
- }
-
- RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
- if (context.patternPropertiesValidatorCount > 0) {
- bool otherValid = false;
- SizeType count = context.patternPropertiesValidatorCount;
- if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
- otherValid = context.patternPropertiesValidators[--count]->IsValid();
-
- bool patternValid = true;
- for (SizeType i = 0; i < count; i++)
- if (!context.patternPropertiesValidators[i]->IsValid()) {
- patternValid = false;
- break;
- }
-
- if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
- if (!patternValid)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
- }
- else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
- if (!patternValid || !otherValid)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
- }
- else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
- }
-
- if (enum_) {
- const uint64_t h = context.factory.GetHashCode(context.hasher);
- for (SizeType i = 0; i < enumCount_; i++)
- if (enum_[i] == h)
- goto foundEnum;
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
- foundEnum:;
- }
-
- if (allOf_.schemas)
- for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
- if (!context.validators[i]->IsValid())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
-
- if (anyOf_.schemas) {
- for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
- if (context.validators[i]->IsValid())
- goto foundAny;
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
- foundAny:;
- }
-
- if (oneOf_.schemas) {
- bool oneValid = false;
- for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
- if (context.validators[i]->IsValid()) {
- if (oneValid)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
- else
- oneValid = true;
- }
- if (!oneValid)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
- }
-
- if (not_ && context.validators[notValidatorIndex_]->IsValid())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
-
- return true;
- }
-
- bool Null(Context& context) const {
- if (!(type_ & (1 << kNullSchemaType)))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
- return CreateParallelValidator(context);
- }
-
- bool Bool(Context& context, bool) const {
- if (!(type_ & (1 << kBooleanSchemaType)))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
- return CreateParallelValidator(context);
- }
-
- bool Int(Context& context, int i) const {
- if (!CheckInt(context, i))
- return false;
- return CreateParallelValidator(context);
- }
-
- bool Uint(Context& context, unsigned u) const {
- if (!CheckUint(context, u))
- return false;
- return CreateParallelValidator(context);
- }
-
- bool Int64(Context& context, int64_t i) const {
- if (!CheckInt(context, i))
- return false;
- return CreateParallelValidator(context);
- }
-
- bool Uint64(Context& context, uint64_t u) const {
- if (!CheckUint(context, u))
- return false;
- return CreateParallelValidator(context);
- }
-
- bool Double(Context& context, double d) const {
- if (!(type_ & (1 << kNumberSchemaType)))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
-
- if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
- return false;
-
- if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
- return false;
-
- if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
- return false;
-
- return CreateParallelValidator(context);
- }
-
- bool String(Context& context, const Ch* str, SizeType length, bool) const {
- if (!(type_ & (1 << kStringSchemaType)))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
-
- if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
- SizeType count;
- if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
- if (count < minLength_)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
- if (count > maxLength_)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
- }
- }
-
- if (pattern_ && !IsPatternMatch(pattern_, str, length))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
-
- return CreateParallelValidator(context);
- }
-
- bool StartObject(Context& context) const {
- if (!(type_ & (1 << kObjectSchemaType)))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
-
- if (hasDependencies_ || hasRequired_) {
- context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
- std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
- }
-
- if (patternProperties_) { // pre-allocate schema array
- SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
- context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
- context.patternPropertiesSchemaCount = 0;
- std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
- }
-
- return CreateParallelValidator(context);
- }
-
- bool Key(Context& context, const Ch* str, SizeType len, bool) const {
- if (patternProperties_) {
- context.patternPropertiesSchemaCount = 0;
- for (SizeType i = 0; i < patternPropertyCount_; i++)
- if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len))
- context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
- }
-
- SizeType index;
- if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
- if (context.patternPropertiesSchemaCount > 0) {
- context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
- context.valueSchema = GetTypeless();
- context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
- }
- else
- context.valueSchema = properties_[index].schema;
-
- if (context.propertyExist)
- context.propertyExist[index] = true;
-
- return true;
- }
-
- if (additionalPropertiesSchema_) {
- if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
- context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
- context.valueSchema = GetTypeless();
- context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
- }
- else
- context.valueSchema = additionalPropertiesSchema_;
- return true;
- }
- else if (additionalProperties_) {
- context.valueSchema = GetTypeless();
- return true;
- }
-
- if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
-
- return true;
- }
-
- bool EndObject(Context& context, SizeType memberCount) const {
- if (hasRequired_)
- for (SizeType index = 0; index < propertyCount_; index++)
- if (properties_[index].required)
- if (!context.propertyExist[index])
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
-
- if (memberCount < minProperties_)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
-
- if (memberCount > maxProperties_)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
-
- if (hasDependencies_) {
- for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
- if (context.propertyExist[sourceIndex]) {
- if (properties_[sourceIndex].dependencies) {
- for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
- if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
- }
- else if (properties_[sourceIndex].dependenciesSchema)
- if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
- }
- }
-
- return true;
- }
-
- bool StartArray(Context& context) const {
- if (!(type_ & (1 << kArraySchemaType)))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
-
- context.arrayElementIndex = 0;
- context.inArray = true;
-
- return CreateParallelValidator(context);
- }
-
- bool EndArray(Context& context, SizeType elementCount) const {
- context.inArray = false;
-
- if (elementCount < minItems_)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
-
- if (elementCount > maxItems_)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
-
- return true;
- }
-
- // Generate functions for string literal according to Ch
-#define RAPIDJSON_STRING_(name, ...) \
- static const ValueType& Get##name##String() {\
- static const Ch s[] = { __VA_ARGS__, '\0' };\
- static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\
- return v;\
- }
-
- RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
- RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
- RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
- RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
- RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
- RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
- RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
- RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
- RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
- RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
- RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
- RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
- RAPIDJSON_STRING_(Not, 'n', 'o', 't')
- RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
- RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
- RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
- RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
- RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
- RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
- RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
- RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
- RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
- RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
- RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
- RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
- RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
- RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
- RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
- RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
- RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
- RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
- RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
- RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
-
-#undef RAPIDJSON_STRING_
-
-private:
- enum SchemaValueType {
- kNullSchemaType,
- kBooleanSchemaType,
- kObjectSchemaType,
- kArraySchemaType,
- kStringSchemaType,
- kNumberSchemaType,
- kIntegerSchemaType,
- kTotalSchemaType
- };
-
-#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
- typedef internal::GenericRegex<EncodingType> RegexType;
-#elif RAPIDJSON_SCHEMA_USE_STDREGEX
- typedef std::basic_regex<Ch> RegexType;
-#else
- typedef char RegexType;
-#endif
-
- struct SchemaArray {
- SchemaArray() : schemas(), count() {}
- ~SchemaArray() { AllocatorType::Free(schemas); }
- const SchemaType** schemas;
- SizeType begin; // begin index of context.validators
- SizeType count;
- };
-
- static const SchemaType* GetTypeless() {
- static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
- return &typeless;
- }
-
- template <typename V1, typename V2>
- void AddUniqueElement(V1& a, const V2& v) {
- for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
- if (*itr == v)
- return;
- V1 c(v, *allocator_);
- a.PushBack(c, *allocator_);
- }
-
- static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
- typename ValueType::ConstMemberIterator itr = value.FindMember(name);
- return itr != value.MemberEnd() ? &(itr->value) : 0;
- }
-
- static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
- if (const ValueType* v = GetMember(value, name))
- if (v->IsBool())
- out = v->GetBool();
- }
-
- static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
- if (const ValueType* v = GetMember(value, name))
- if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
- out = static_cast<SizeType>(v->GetUint64());
- }
-
- void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
- if (const ValueType* v = GetMember(value, name)) {
- if (v->IsArray() && v->Size() > 0) {
- PointerType q = p.Append(name, allocator_);
- out.count = v->Size();
- out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
- memset(out.schemas, 0, sizeof(Schema*)* out.count);
- for (SizeType i = 0; i < out.count; i++)
- schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
- out.begin = validatorCount_;
- validatorCount_ += out.count;
- }
- }
- }
-
-#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
- template <typename ValueType>
- RegexType* CreatePattern(const ValueType& value) {
- if (value.IsString()) {
- RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString());
- if (!r->IsValid()) {
- r->~RegexType();
- AllocatorType::Free(r);
- r = 0;
- }
- return r;
- }
- return 0;
- }
-
- static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
- return pattern->Search(str);
- }
-#elif RAPIDJSON_SCHEMA_USE_STDREGEX
- template <typename ValueType>
- RegexType* CreatePattern(const ValueType& value) {
- if (value.IsString())
- try {
- return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
- }
- catch (const std::regex_error&) {
- }
- return 0;
- }
-
- static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
- std::match_results<const Ch*> r;
- return std::regex_search(str, str + length, r, *pattern);
- }
-#else
- template <typename ValueType>
- RegexType* CreatePattern(const ValueType&) { return 0; }
-
- static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
-#endif // RAPIDJSON_SCHEMA_USE_STDREGEX
-
- void AddType(const ValueType& type) {
- if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
- else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
- else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
- else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
- else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
- else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
- else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
- }
-
- bool CreateParallelValidator(Context& context) const {
- if (enum_ || context.arrayUniqueness)
- context.hasher = context.factory.CreateHasher();
-
- if (validatorCount_) {
- RAPIDJSON_ASSERT(context.validators == 0);
- context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
- context.validatorCount = validatorCount_;
-
- if (allOf_.schemas)
- CreateSchemaValidators(context, allOf_);
-
- if (anyOf_.schemas)
- CreateSchemaValidators(context, anyOf_);
-
- if (oneOf_.schemas)
- CreateSchemaValidators(context, oneOf_);
-
- if (not_)
- context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
-
- if (hasSchemaDependencies_) {
- for (SizeType i = 0; i < propertyCount_; i++)
- if (properties_[i].dependenciesSchema)
- context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
- }
- }
-
- return true;
- }
-
- void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
- for (SizeType i = 0; i < schemas.count; i++)
- context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
- }
-
- // O(n)
- bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
- SizeType len = name.GetStringLength();
- const Ch* str = name.GetString();
- for (SizeType index = 0; index < propertyCount_; index++)
- if (properties_[index].name.GetStringLength() == len &&
- (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
- {
- *outIndex = index;
- return true;
- }
- return false;
- }
-
- bool CheckInt(Context& context, int64_t i) const {
- if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
-
- if (!minimum_.IsNull()) {
- if (minimum_.IsInt64()) {
- if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
- }
- else if (minimum_.IsUint64()) {
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
- }
- else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
- return false;
- }
-
- if (!maximum_.IsNull()) {
- if (maximum_.IsInt64()) {
- if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
- }
- else if (maximum_.IsUint64())
- /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64()
- else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
- return false;
- }
-
- if (!multipleOf_.IsNull()) {
- if (multipleOf_.IsUint64()) {
- if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
- }
- else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
- return false;
- }
-
- return true;
- }
-
- bool CheckUint(Context& context, uint64_t i) const {
- if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
-
- if (!minimum_.IsNull()) {
- if (minimum_.IsUint64()) {
- if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
- }
- else if (minimum_.IsInt64())
- /* do nothing */; // i >= 0 > minimum.Getint64()
- else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
- return false;
- }
-
- if (!maximum_.IsNull()) {
- if (maximum_.IsUint64()) {
- if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
- }
- else if (maximum_.IsInt64())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
- else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
- return false;
- }
-
- if (!multipleOf_.IsNull()) {
- if (multipleOf_.IsUint64()) {
- if (i % multipleOf_.GetUint64() != 0)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
- }
- else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
- return false;
- }
-
- return true;
- }
-
- bool CheckDoubleMinimum(Context& context, double d) const {
- if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
- return true;
- }
-
- bool CheckDoubleMaximum(Context& context, double d) const {
- if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
- return true;
- }
-
- bool CheckDoubleMultipleOf(Context& context, double d) const {
- double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
- double q = std::floor(a / b);
- double r = a - q * b;
- if (r > 0.0)
- RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
- return true;
- }
-
- struct Property {
- Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
- ~Property() { AllocatorType::Free(dependencies); }
- SValue name;
- const SchemaType* schema;
- const SchemaType* dependenciesSchema;
- SizeType dependenciesValidatorIndex;
- bool* dependencies;
- bool required;
- };
-
- struct PatternProperty {
- PatternProperty() : schema(), pattern() {}
- ~PatternProperty() {
- if (pattern) {
- pattern->~RegexType();
- AllocatorType::Free(pattern);
- }
- }
- const SchemaType* schema;
- RegexType* pattern;
- };
-
- AllocatorType* allocator_;
- uint64_t* enum_;
- SizeType enumCount_;
- SchemaArray allOf_;
- SchemaArray anyOf_;
- SchemaArray oneOf_;
- const SchemaType* not_;
- unsigned type_; // bitmask of kSchemaType
- SizeType validatorCount_;
- SizeType notValidatorIndex_;
-
- Property* properties_;
- const SchemaType* additionalPropertiesSchema_;
- PatternProperty* patternProperties_;
- SizeType patternPropertyCount_;
- SizeType propertyCount_;
- SizeType minProperties_;
- SizeType maxProperties_;
- bool additionalProperties_;
- bool hasDependencies_;
- bool hasRequired_;
- bool hasSchemaDependencies_;
-
- const SchemaType* additionalItemsSchema_;
- const SchemaType* itemsList_;
- const SchemaType** itemsTuple_;
- SizeType itemsTupleCount_;
- SizeType minItems_;
- SizeType maxItems_;
- bool additionalItems_;
- bool uniqueItems_;
-
- RegexType* pattern_;
- SizeType minLength_;
- SizeType maxLength_;
-
- SValue minimum_;
- SValue maximum_;
- SValue multipleOf_;
- bool exclusiveMinimum_;
- bool exclusiveMaximum_;
-};
-
-template<typename Stack, typename Ch>
-struct TokenHelper {
- RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
- *documentStack.template Push<Ch>() = '/';
- char buffer[21];
- size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
- for (size_t i = 0; i < length; i++)
- *documentStack.template Push<Ch>() = buffer[i];
- }
-};
-
-// Partial specialized version for char to prevent buffer copying.
-template <typename Stack>
-struct TokenHelper<Stack, char> {
- RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
- if (sizeof(SizeType) == 4) {
- char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
- *buffer++ = '/';
- const char* end = internal::u32toa(index, buffer);
- documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
- }
- else {
- char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
- *buffer++ = '/';
- const char* end = internal::u64toa(index, buffer);
- documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
- }
- }
-};
-
-} // namespace internal
-
-///////////////////////////////////////////////////////////////////////////////
-// IGenericRemoteSchemaDocumentProvider
-
-template <typename SchemaDocumentType>
-class IGenericRemoteSchemaDocumentProvider {
-public:
- typedef typename SchemaDocumentType::Ch Ch;
-
- virtual ~IGenericRemoteSchemaDocumentProvider() {}
- virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericSchemaDocument
-
-//! JSON schema document.
-/*!
- A JSON schema document is a compiled version of a JSON schema.
- It is basically a tree of internal::Schema.
-
- \note This is an immutable class (i.e. its instance cannot be modified after construction).
- \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding.
- \tparam Allocator Allocator type for allocating memory of this document.
-*/
-template <typename ValueT, typename Allocator = CrtAllocator>
-class GenericSchemaDocument {
-public:
- typedef ValueT ValueType;
- typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
- typedef Allocator AllocatorType;
- typedef typename ValueType::EncodingType EncodingType;
- typedef typename EncodingType::Ch Ch;
- typedef internal::Schema<GenericSchemaDocument> SchemaType;
- typedef GenericPointer<ValueType, Allocator> PointerType;
- friend class internal::Schema<GenericSchemaDocument>;
- template <typename, typename, typename>
- friend class GenericSchemaValidator;
-
- //! Constructor.
- /*!
- Compile a JSON document into schema document.
-
- \param document A JSON document as source.
- \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
- \param allocator An optional allocator instance for allocating memory. Can be null.
- */
- explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
- remoteProvider_(remoteProvider),
- allocator_(allocator),
- ownAllocator_(),
- root_(),
- schemaMap_(allocator, kInitialSchemaMapSize),
- schemaRef_(allocator, kInitialSchemaRefSize)
- {
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
-
- // Generate root schema, it will call CreateSchema() to create sub-schemas,
- // And call AddRefSchema() if there are $ref.
- CreateSchemaRecursive(&root_, PointerType(), document, document);
-
- // Resolve $ref
- while (!schemaRef_.Empty()) {
- SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
- if (const SchemaType* s = GetSchema(refEntry->target)) {
- if (refEntry->schema)
- *refEntry->schema = s;
-
- // Create entry in map if not exist
- if (!GetSchema(refEntry->source)) {
- new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
- }
- }
- refEntry->~SchemaRefEntry();
- }
-
- RAPIDJSON_ASSERT(root_ != 0);
-
- schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move constructor in C++11
- GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
- remoteProvider_(rhs.remoteProvider_),
- allocator_(rhs.allocator_),
- ownAllocator_(rhs.ownAllocator_),
- root_(rhs.root_),
- schemaMap_(std::move(rhs.schemaMap_)),
- schemaRef_(std::move(rhs.schemaRef_))
- {
- rhs.remoteProvider_ = 0;
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- }
-#endif
-
- //! Destructor
- ~GenericSchemaDocument() {
- while (!schemaMap_.Empty())
- schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
-
- RAPIDJSON_DELETE(ownAllocator_);
- }
-
- //! Get the root schema.
- const SchemaType& GetRoot() const { return *root_; }
-
-private:
- //! Prohibit copying
- GenericSchemaDocument(const GenericSchemaDocument&);
- //! Prohibit assignment
- GenericSchemaDocument& operator=(const GenericSchemaDocument&);
-
- struct SchemaRefEntry {
- SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
- PointerType source;
- PointerType target;
- const SchemaType** schema;
- };
-
- struct SchemaEntry {
- SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
- ~SchemaEntry() {
- if (owned) {
- schema->~SchemaType();
- Allocator::Free(schema);
- }
- }
- PointerType pointer;
- SchemaType* schema;
- bool owned;
- };
-
- void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
- if (schema)
- *schema = SchemaType::GetTypeless();
-
- if (v.GetType() == kObjectType) {
- const SchemaType* s = GetSchema(pointer);
- if (!s)
- CreateSchema(schema, pointer, v, document);
-
- for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
- CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
- }
- else if (v.GetType() == kArrayType)
- for (SizeType i = 0; i < v.Size(); i++)
- CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
- }
-
- void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
- RAPIDJSON_ASSERT(pointer.IsValid());
- if (v.IsObject()) {
- if (!HandleRefSchema(pointer, schema, v, document)) {
- SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
- new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
- if (schema)
- *schema = s;
- }
- }
- }
-
- bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
- static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
- static const ValueType kRefValue(kRefString, 4);
-
- typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
- if (itr == v.MemberEnd())
- return false;
-
- if (itr->value.IsString()) {
- SizeType len = itr->value.GetStringLength();
- if (len > 0) {
- const Ch* s = itr->value.GetString();
- SizeType i = 0;
- while (i < len && s[i] != '#') // Find the first #
- i++;
-
- if (i > 0) { // Remote reference, resolve immediately
- if (remoteProvider_) {
- if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
- PointerType pointer(&s[i], len - i, allocator_);
- if (pointer.IsValid()) {
- if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
- if (schema)
- *schema = sc;
- return true;
- }
- }
- }
- }
- }
- else if (s[i] == '#') { // Local reference, defer resolution
- PointerType pointer(&s[i], len - i, allocator_);
- if (pointer.IsValid()) {
- if (const ValueType* nv = pointer.Get(document))
- if (HandleRefSchema(source, schema, *nv, document))
- return true;
-
- new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- const SchemaType* GetSchema(const PointerType& pointer) const {
- for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
- if (pointer == target->pointer)
- return target->schema;
- return 0;
- }
-
- PointerType GetPointer(const SchemaType* schema) const {
- for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
- if (schema == target->schema)
- return target->pointer;
- return PointerType();
- }
-
- static const size_t kInitialSchemaMapSize = 64;
- static const size_t kInitialSchemaRefSize = 64;
-
- IRemoteSchemaDocumentProviderType* remoteProvider_;
- Allocator *allocator_;
- Allocator *ownAllocator_;
- const SchemaType* root_; //!< Root schema.
- internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
- internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
-};
-
-//! GenericSchemaDocument using Value type.
-typedef GenericSchemaDocument<Value> SchemaDocument;
-//! IGenericRemoteSchemaDocumentProvider using SchemaDocument.
-typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericSchemaValidator
-
-//! JSON Schema Validator.
-/*!
- A SAX style JSON schema validator.
- It uses a \c GenericSchemaDocument to validate SAX events.
- It delegates the incoming SAX events to an output handler.
- The default output handler does nothing.
- It can be reused multiple times by calling \c Reset().
-
- \tparam SchemaDocumentType Type of schema document.
- \tparam OutputHandler Type of output handler. Default handler does nothing.
- \tparam StateAllocator Allocator for storing the internal validation states.
-*/
-template <
- typename SchemaDocumentType,
- typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
- typename StateAllocator = CrtAllocator>
-class GenericSchemaValidator :
- public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
- public internal::ISchemaValidator
-{
-public:
- typedef typename SchemaDocumentType::SchemaType SchemaType;
- typedef typename SchemaDocumentType::PointerType PointerType;
- typedef typename SchemaType::EncodingType EncodingType;
- typedef typename EncodingType::Ch Ch;
-
- //! Constructor without output handler.
- /*!
- \param schemaDocument The schema document to conform to.
- \param allocator Optional allocator for storing internal validation states.
- \param schemaStackCapacity Optional initial capacity of schema path stack.
- \param documentStackCapacity Optional initial capacity of document path stack.
- */
- GenericSchemaValidator(
- const SchemaDocumentType& schemaDocument,
- StateAllocator* allocator = 0,
- size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
- size_t documentStackCapacity = kDefaultDocumentStackCapacity)
- :
- schemaDocument_(&schemaDocument),
- root_(schemaDocument.GetRoot()),
- outputHandler_(GetNullHandler()),
- stateAllocator_(allocator),
- ownStateAllocator_(0),
- schemaStack_(allocator, schemaStackCapacity),
- documentStack_(allocator, documentStackCapacity),
- valid_(true)
-#if RAPIDJSON_SCHEMA_VERBOSE
- , depth_(0)
-#endif
- {
- }
-
- //! Constructor with output handler.
- /*!
- \param schemaDocument The schema document to conform to.
- \param allocator Optional allocator for storing internal validation states.
- \param schemaStackCapacity Optional initial capacity of schema path stack.
- \param documentStackCapacity Optional initial capacity of document path stack.
- */
- GenericSchemaValidator(
- const SchemaDocumentType& schemaDocument,
- OutputHandler& outputHandler,
- StateAllocator* allocator = 0,
- size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
- size_t documentStackCapacity = kDefaultDocumentStackCapacity)
- :
- schemaDocument_(&schemaDocument),
- root_(schemaDocument.GetRoot()),
- outputHandler_(outputHandler),
- stateAllocator_(allocator),
- ownStateAllocator_(0),
- schemaStack_(allocator, schemaStackCapacity),
- documentStack_(allocator, documentStackCapacity),
- valid_(true)
-#if RAPIDJSON_SCHEMA_VERBOSE
- , depth_(0)
-#endif
- {
- }
-
- //! Destructor.
- ~GenericSchemaValidator() {
- Reset();
- RAPIDJSON_DELETE(ownStateAllocator_);
- }
-
- //! Reset the internal states.
- void Reset() {
- while (!schemaStack_.Empty())
- PopSchema();
- documentStack_.Clear();
- valid_ = true;
- }
-
- //! Checks whether the current state is valid.
- // Implementation of ISchemaValidator
- virtual bool IsValid() const { return valid_; }
-
- //! Gets the JSON pointer pointed to the invalid schema.
- PointerType GetInvalidSchemaPointer() const {
- return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
- }
-
- //! Gets the keyword of invalid schema.
- const Ch* GetInvalidSchemaKeyword() const {
- return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
- }
-
- //! Gets the JSON pointer pointed to the invalid value.
- PointerType GetInvalidDocumentPointer() const {
- return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
- }
-
-#if RAPIDJSON_SCHEMA_VERBOSE
-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
-RAPIDJSON_MULTILINEMACRO_BEGIN\
- *documentStack_.template Push<Ch>() = '\0';\
- documentStack_.template Pop<Ch>(1);\
- internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
-RAPIDJSON_MULTILINEMACRO_END
-#else
-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
-#endif
-
-#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
- if (!valid_) return false; \
- if (!BeginValue() || !CurrentSchema().method arg1) {\
- RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
- return valid_ = false;\
- }
-
-#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
- for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
- if (context->hasher)\
- static_cast<HasherType*>(context->hasher)->method arg2;\
- if (context->validators)\
- for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
- static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
- if (context->patternPropertiesValidators)\
- for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
- static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
- }
-
-#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
- return valid_ = EndValue() && outputHandler_.method arg2
-
-#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
- RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
- RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
- RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
-
- bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); }
- bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
- bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
- bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
- bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
- bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
- bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
- bool RawNumber(const Ch* str, SizeType length, bool copy)
- { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
- bool String(const Ch* str, SizeType length, bool copy)
- { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
-
- bool StartObject() {
- RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
- RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
- return valid_ = outputHandler_.StartObject();
- }
-
- bool Key(const Ch* str, SizeType len, bool copy) {
- if (!valid_) return false;
- AppendToken(str, len);
- if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
- RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
- return valid_ = outputHandler_.Key(str, len, copy);
- }
-
- bool EndObject(SizeType memberCount) {
- if (!valid_) return false;
- RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
- if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
- RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
- }
-
- bool StartArray() {
- RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
- RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
- return valid_ = outputHandler_.StartArray();
- }
-
- bool EndArray(SizeType elementCount) {
- if (!valid_) return false;
- RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
- if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
- RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
- }
-
-#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
-#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
-#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
-#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
-
- // Implementation of ISchemaStateFactory<SchemaType>
- virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
- return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root,
-#if RAPIDJSON_SCHEMA_VERBOSE
- depth_ + 1,
-#endif
- &GetStateAllocator());
- }
-
- virtual void DestroySchemaValidator(ISchemaValidator* validator) {
- GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
- v->~GenericSchemaValidator();
- StateAllocator::Free(v);
- }
-
- virtual void* CreateHasher() {
- return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
- }
-
- virtual uint64_t GetHashCode(void* hasher) {
- return static_cast<HasherType*>(hasher)->GetHashCode();
- }
-
- virtual void DestroryHasher(void* hasher) {
- HasherType* h = static_cast<HasherType*>(hasher);
- h->~HasherType();
- StateAllocator::Free(h);
- }
-
- virtual void* MallocState(size_t size) {
- return GetStateAllocator().Malloc(size);
- }
-
- virtual void FreeState(void* p) {
- return StateAllocator::Free(p);
- }
-
-private:
- typedef typename SchemaType::Context Context;
- typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
- typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
-
- GenericSchemaValidator(
- const SchemaDocumentType& schemaDocument,
- const SchemaType& root,
-#if RAPIDJSON_SCHEMA_VERBOSE
- unsigned depth,
-#endif
- StateAllocator* allocator = 0,
- size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
- size_t documentStackCapacity = kDefaultDocumentStackCapacity)
- :
- schemaDocument_(&schemaDocument),
- root_(root),
- outputHandler_(GetNullHandler()),
- stateAllocator_(allocator),
- ownStateAllocator_(0),
- schemaStack_(allocator, schemaStackCapacity),
- documentStack_(allocator, documentStackCapacity),
- valid_(true)
-#if RAPIDJSON_SCHEMA_VERBOSE
- , depth_(depth)
-#endif
- {
- }
-
- StateAllocator& GetStateAllocator() {
- if (!stateAllocator_)
- stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator());
- return *stateAllocator_;
- }
-
- bool BeginValue() {
- if (schemaStack_.Empty())
- PushSchema(root_);
- else {
- if (CurrentContext().inArray)
- internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
-
- if (!CurrentSchema().BeginValue(CurrentContext()))
- return false;
-
- SizeType count = CurrentContext().patternPropertiesSchemaCount;
- const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
- typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
- bool valueUniqueness = CurrentContext().valueUniqueness;
- if (CurrentContext().valueSchema)
- PushSchema(*CurrentContext().valueSchema);
-
- if (count > 0) {
- CurrentContext().objectPatternValidatorType = patternValidatorType;
- ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
- SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
- va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
- for (SizeType i = 0; i < count; i++)
- va[validatorCount++] = CreateSchemaValidator(*sa[i]);
- }
-
- CurrentContext().arrayUniqueness = valueUniqueness;
- }
- return true;
- }
-
- bool EndValue() {
- if (!CurrentSchema().EndValue(CurrentContext()))
- return false;
-
-#if RAPIDJSON_SCHEMA_VERBOSE
- GenericStringBuffer<EncodingType> sb;
- schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
-
- *documentStack_.template Push<Ch>() = '\0';
- documentStack_.template Pop<Ch>(1);
- internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
-#endif
-
- uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
-
- PopSchema();
-
- if (!schemaStack_.Empty()) {
- Context& context = CurrentContext();
- if (context.valueUniqueness) {
- HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
- if (!a)
- CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
- for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
- if (itr->GetUint64() == h)
- RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
- a->PushBack(h, GetStateAllocator());
- }
- }
-
- // Remove the last token of document pointer
- while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
- ;
-
- return true;
- }
-
- void AppendToken(const Ch* str, SizeType len) {
- documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
- *documentStack_.template PushUnsafe<Ch>() = '/';
- for (SizeType i = 0; i < len; i++) {
- if (str[i] == '~') {
- *documentStack_.template PushUnsafe<Ch>() = '~';
- *documentStack_.template PushUnsafe<Ch>() = '0';
- }
- else if (str[i] == '/') {
- *documentStack_.template PushUnsafe<Ch>() = '~';
- *documentStack_.template PushUnsafe<Ch>() = '1';
- }
- else
- *documentStack_.template PushUnsafe<Ch>() = str[i];
- }
- }
-
- RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); }
-
- RAPIDJSON_FORCEINLINE void PopSchema() {
- Context* c = schemaStack_.template Pop<Context>(1);
- if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
- a->~HashCodeArray();
- StateAllocator::Free(a);
- }
- c->~Context();
- }
-
- const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
- Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
- const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
-
- static OutputHandler& GetNullHandler() {
- static OutputHandler nullHandler;
- return nullHandler;
- }
-
- static const size_t kDefaultSchemaStackCapacity = 1024;
- static const size_t kDefaultDocumentStackCapacity = 256;
- const SchemaDocumentType* schemaDocument_;
- const SchemaType& root_;
- OutputHandler& outputHandler_;
- StateAllocator* stateAllocator_;
- StateAllocator* ownStateAllocator_;
- internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
- internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
- bool valid_;
-#if RAPIDJSON_SCHEMA_VERBOSE
- unsigned depth_;
-#endif
-};
-
-typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
-
-///////////////////////////////////////////////////////////////////////////////
-// SchemaValidatingReader
-
-//! A helper class for parsing with validation.
-/*!
- This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate().
-
- \tparam parseFlags Combination of \ref ParseFlag.
- \tparam InputStream Type of input stream, implementing Stream concept.
- \tparam SourceEncoding Encoding of the input stream.
- \tparam SchemaDocumentType Type of schema document.
- \tparam StackAllocator Allocator type for stack.
-*/
-template <
- unsigned parseFlags,
- typename InputStream,
- typename SourceEncoding,
- typename SchemaDocumentType = SchemaDocument,
- typename StackAllocator = CrtAllocator>
-class SchemaValidatingReader {
-public:
- typedef typename SchemaDocumentType::PointerType PointerType;
- typedef typename InputStream::Ch Ch;
-
- //! Constructor
- /*!
- \param is Input stream.
- \param sd Schema document.
- */
- SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {}
-
- template <typename Handler>
- bool operator()(Handler& handler) {
- GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
- GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
- parseResult_ = reader.template Parse<parseFlags>(is_, validator);
-
- isValid_ = validator.IsValid();
- if (isValid_) {
- invalidSchemaPointer_ = PointerType();
- invalidSchemaKeyword_ = 0;
- invalidDocumentPointer_ = PointerType();
- }
- else {
- invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
- invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
- invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
- }
-
- return parseResult_;
- }
-
- const ParseResult& GetParseResult() const { return parseResult_; }
- bool IsValid() const { return isValid_; }
- const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
- const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
- const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
-
-private:
- InputStream& is_;
- const SchemaDocumentType& sd_;
-
- ParseResult parseResult_;
- PointerType invalidSchemaPointer_;
- const Ch* invalidSchemaKeyword_;
- PointerType invalidDocumentPointer_;
- bool isValid_;
-};
-
-RAPIDJSON_NAMESPACE_END
-RAPIDJSON_DIAG_POP
-
-#endif // RAPIDJSON_SCHEMA_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#include "rapidjson.h"
-
-#ifndef RAPIDJSON_STREAM_H_
-#define RAPIDJSON_STREAM_H_
-
-#include "encodings.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Stream
-
-/*! \class rapidjson::Stream
- \brief Concept for reading and writing characters.
-
- For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
-
- For write-only stream, only need to implement Put() and Flush().
-
-\code
-concept Stream {
- typename Ch; //!< Character type of the stream.
-
- //! Read the current character from stream without moving the read cursor.
- Ch Peek() const;
-
- //! Read the current character from stream and moving the read cursor to next character.
- Ch Take();
-
- //! Get the current read cursor.
- //! \return Number of characters read from start.
- size_t Tell();
-
- //! Begin writing operation at the current read pointer.
- //! \return The begin writer pointer.
- Ch* PutBegin();
-
- //! Write a character.
- void Put(Ch c);
-
- //! Flush the buffer.
- void Flush();
-
- //! End the writing operation.
- //! \param begin The begin write pointer returned by PutBegin().
- //! \return Number of characters written.
- size_t PutEnd(Ch* begin);
-}
-\endcode
-*/
-
-//! Provides additional information for stream.
-/*!
- By using traits pattern, this type provides a default configuration for stream.
- For custom stream, this type can be specialized for other configuration.
- See TEST(Reader, CustomStringStream) in readertest.cpp for example.
-*/
-template<typename Stream>
-struct StreamTraits {
- //! Whether to make local copy of stream for optimization during parsing.
- /*!
- By default, for safety, streams do not use local copy optimization.
- Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
- */
- enum { copyOptimization = 0 };
-};
-
-//! Reserve n characters for writing to a stream.
-template<typename Stream>
-inline void PutReserve(Stream& stream, size_t count) {
- (void)stream;
- (void)count;
-}
-
-//! Write character to a stream, presuming buffer is reserved.
-template<typename Stream>
-inline void PutUnsafe(Stream& stream, typename Stream::Ch c) {
- stream.Put(c);
-}
-
-//! Put N copies of a character to a stream.
-template<typename Stream, typename Ch>
-inline void PutN(Stream& stream, Ch c, size_t n) {
- PutReserve(stream, n);
- for (size_t i = 0; i < n; i++)
- PutUnsafe(stream, c);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// StringStream
-
-//! Read-only string stream.
-/*! \note implements Stream concept
-*/
-template <typename Encoding>
-struct GenericStringStream {
- typedef typename Encoding::Ch Ch;
-
- GenericStringStream(const Ch *src) : src_(src), head_(src) {}
-
- Ch Peek() const { return *src_; }
- Ch Take() { return *src_++; }
- size_t Tell() const { return static_cast<size_t>(src_ - head_); }
-
- Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
- void Put(Ch) { RAPIDJSON_ASSERT(false); }
- void Flush() { RAPIDJSON_ASSERT(false); }
- size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
-
- const Ch* src_; //!< Current read position.
- const Ch* head_; //!< Original head of the string.
-};
-
-template <typename Encoding>
-struct StreamTraits<GenericStringStream<Encoding> > {
- enum { copyOptimization = 1 };
-};
-
-//! String stream with UTF8 encoding.
-typedef GenericStringStream<UTF8<> > StringStream;
-
-///////////////////////////////////////////////////////////////////////////////
-// InsituStringStream
-
-//! A read-write string stream.
-/*! This string stream is particularly designed for in-situ parsing.
- \note implements Stream concept
-*/
-template <typename Encoding>
-struct GenericInsituStringStream {
- typedef typename Encoding::Ch Ch;
-
- GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
-
- // Read
- Ch Peek() { return *src_; }
- Ch Take() { return *src_++; }
- size_t Tell() { return static_cast<size_t>(src_ - head_); }
-
- // Write
- void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
-
- Ch* PutBegin() { return dst_ = src_; }
- size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
- void Flush() {}
-
- Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
- void Pop(size_t count) { dst_ -= count; }
-
- Ch* src_;
- Ch* dst_;
- Ch* head_;
-};
-
-template <typename Encoding>
-struct StreamTraits<GenericInsituStringStream<Encoding> > {
- enum { copyOptimization = 1 };
-};
-
-//! Insitu string stream with UTF8 encoding.
-typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_STREAM_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_STRINGBUFFER_H_
-#define RAPIDJSON_STRINGBUFFER_H_
-
-#include "stream.h"
-#include "internal/stack.h"
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#include <utility> // std::move
-#endif
-
-#include "internal/stack.h"
-
-#if defined(__clang__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(c++98-compat)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Represents an in-memory output stream.
-/*!
- \tparam Encoding Encoding of the stream.
- \tparam Allocator type for allocating memory buffer.
- \note implements Stream concept
-*/
-template <typename Encoding, typename Allocator = CrtAllocator>
-class GenericStringBuffer {
-public:
- typedef typename Encoding::Ch Ch;
-
- GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
- GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
- if (&rhs != this)
- stack_ = std::move(rhs.stack_);
- return *this;
- }
-#endif
-
- void Put(Ch c) { *stack_.template Push<Ch>() = c; }
- void PutUnsafe(Ch c) { *stack_.template PushUnsafe<Ch>() = c; }
- void Flush() {}
-
- void Clear() { stack_.Clear(); }
- void ShrinkToFit() {
- // Push and pop a null terminator. This is safe.
- *stack_.template Push<Ch>() = '\0';
- stack_.ShrinkToFit();
- stack_.template Pop<Ch>(1);
- }
-
- void Reserve(size_t count) { stack_.template Reserve<Ch>(count); }
- Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
- Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe<Ch>(count); }
- void Pop(size_t count) { stack_.template Pop<Ch>(count); }
-
- const Ch* GetString() const {
- // Push and pop a null terminator. This is safe.
- *stack_.template Push<Ch>() = '\0';
- stack_.template Pop<Ch>(1);
-
- return stack_.template Bottom<Ch>();
- }
-
- size_t GetSize() const { return stack_.GetSize(); }
-
- static const size_t kDefaultCapacity = 256;
- mutable internal::Stack<Allocator> stack_;
-
-private:
- // Prohibit copy constructor & assignment operator.
- GenericStringBuffer(const GenericStringBuffer&);
- GenericStringBuffer& operator=(const GenericStringBuffer&);
-};
-
-//! String buffer with UTF8 encoding
-typedef GenericStringBuffer<UTF8<> > StringBuffer;
-
-template<typename Encoding, typename Allocator>
-inline void PutReserve(GenericStringBuffer<Encoding, Allocator>& stream, size_t count) {
- stream.Reserve(count);
-}
-
-template<typename Encoding, typename Allocator>
-inline void PutUnsafe(GenericStringBuffer<Encoding, Allocator>& stream, typename Encoding::Ch c) {
- stream.PutUnsafe(c);
-}
-
-//! Implement specialized version of PutN() with memset() for better performance.
-template<>
-inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
- std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#if defined(__clang__)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_STRINGBUFFER_H_
+++ /dev/null
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_WRITER_H_
-#define RAPIDJSON_WRITER_H_
-
-#include "stream.h"
-#include "internal/stack.h"
-#include "internal/strfunc.h"
-#include "internal/dtoa.h"
-#include "internal/itoa.h"
-#include "stringbuffer.h"
-#include <new> // placement new
-
-#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
-#include <intrin.h>
-#pragma intrinsic(_BitScanForward)
-#endif
-#ifdef RAPIDJSON_SSE42
-#include <nmmintrin.h>
-#elif defined(RAPIDJSON_SSE2)
-#include <emmintrin.h>
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(padded)
-RAPIDJSON_DIAG_OFF(unreachable-code)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// WriteFlag
-
-/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
- \ingroup RAPIDJSON_CONFIG
- \brief User-defined kWriteDefaultFlags definition.
-
- User can define this as any \c WriteFlag combinations.
-*/
-#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
-#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
-#endif
-
-//! Combination of writeFlags
-enum WriteFlag {
- kWriteNoFlags = 0, //!< No flags are set.
- kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
- kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
- kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
-};
-
-//! JSON writer
-/*! Writer implements the concept Handler.
- It generates JSON text by events to an output os.
-
- User may programmatically calls the functions of a writer to generate JSON text.
-
- On the other side, a writer can also be passed to objects that generates events,
-
- for example Reader::Parse() and Document::Accept().
-
- \tparam OutputStream Type of output stream.
- \tparam SourceEncoding Encoding of source string.
- \tparam TargetEncoding Encoding of output stream.
- \tparam StackAllocator Type of allocator for allocating memory of stack.
- \note implements Handler concept
-*/
-template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
-class Writer {
-public:
- typedef typename SourceEncoding::Ch Ch;
-
- static const int kDefaultMaxDecimalPlaces = 324;
-
- //! Constructor
- /*! \param os Output stream.
- \param stackAllocator User supplied allocator. If it is null, it will create a private one.
- \param levelDepth Initial capacity of stack.
- */
- explicit
- Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
- os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
-
- explicit
- Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
- os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
-
- //! Reset the writer with a new stream.
- /*!
- This function reset the writer with a new stream and default settings,
- in order to make a Writer object reusable for output multiple JSONs.
-
- \param os New output stream.
- \code
- Writer<OutputStream> writer(os1);
- writer.StartObject();
- // ...
- writer.EndObject();
-
- writer.Reset(os2);
- writer.StartObject();
- // ...
- writer.EndObject();
- \endcode
- */
- void Reset(OutputStream& os) {
- os_ = &os;
- hasRoot_ = false;
- level_stack_.Clear();
- }
-
- //! Checks whether the output is a complete JSON.
- /*!
- A complete JSON has a complete root object or array.
- */
- bool IsComplete() const {
- return hasRoot_ && level_stack_.Empty();
- }
-
- int GetMaxDecimalPlaces() const {
- return maxDecimalPlaces_;
- }
-
- //! Sets the maximum number of decimal places for double output.
- /*!
- This setting truncates the output with specified number of decimal places.
-
- For example,
-
- \code
- writer.SetMaxDecimalPlaces(3);
- writer.StartArray();
- writer.Double(0.12345); // "0.123"
- writer.Double(0.0001); // "0.0"
- writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
- writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
- writer.EndArray();
- \endcode
-
- The default setting does not truncate any decimal places. You can restore to this setting by calling
- \code
- writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
- \endcode
- */
- void SetMaxDecimalPlaces(int maxDecimalPlaces) {
- maxDecimalPlaces_ = maxDecimalPlaces;
- }
-
- /*!@name Implementation of Handler
- \see Handler
- */
- //@{
-
- bool Null() { Prefix(kNullType); return EndValue(WriteNull()); }
- bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); }
- bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); }
- bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); }
- bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); }
- bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); }
-
- //! Writes the given \c double value to the stream
- /*!
- \param d The value to be written.
- \return Whether it is succeed.
- */
- bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
-
- bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
- (void)copy;
- Prefix(kNumberType);
- return EndValue(WriteString(str, length));
- }
-
- bool String(const Ch* str, SizeType length, bool copy = false) {
- (void)copy;
- Prefix(kStringType);
- return EndValue(WriteString(str, length));
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool String(const std::basic_string<Ch>& str) {
- return String(str.data(), SizeType(str.size()));
- }
-#endif
-
- bool StartObject() {
- Prefix(kObjectType);
- new (level_stack_.template Push<Level>()) Level(false);
- return WriteStartObject();
- }
-
- bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
-
- bool EndObject(SizeType memberCount = 0) {
- (void)memberCount;
- RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
- RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
- level_stack_.template Pop<Level>(1);
- return EndValue(WriteEndObject());
- }
-
- bool StartArray() {
- Prefix(kArrayType);
- new (level_stack_.template Push<Level>()) Level(true);
- return WriteStartArray();
- }
-
- bool EndArray(SizeType elementCount = 0) {
- (void)elementCount;
- RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
- RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
- level_stack_.template Pop<Level>(1);
- return EndValue(WriteEndArray());
- }
- //@}
-
- /*! @name Convenience extensions */
- //@{
-
- //! Simpler but slower overload.
- bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
- bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
-
- //@}
-
- //! Write a raw JSON value.
- /*!
- For user to write a stringified JSON as a value.
-
- \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range.
- \param length Length of the json.
- \param type Type of the root of json.
- */
- bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
-
-protected:
- //! Information for each nested level
- struct Level {
- Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
- size_t valueCount; //!< number of values in this level
- bool inArray; //!< true if in array, otherwise in object
- };
-
- static const size_t kDefaultLevelDepth = 32;
-
- bool WriteNull() {
- PutReserve(*os_, 4);
- PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
- }
-
- bool WriteBool(bool b) {
- if (b) {
- PutReserve(*os_, 4);
- PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e');
- }
- else {
- PutReserve(*os_, 5);
- PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e');
- }
- return true;
- }
-
- bool WriteInt(int i) {
- char buffer[11];
- const char* end = internal::i32toa(i, buffer);
- PutReserve(*os_, static_cast<size_t>(end - buffer));
- for (const char* p = buffer; p != end; ++p)
- PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
- return true;
- }
-
- bool WriteUint(unsigned u) {
- char buffer[10];
- const char* end = internal::u32toa(u, buffer);
- PutReserve(*os_, static_cast<size_t>(end - buffer));
- for (const char* p = buffer; p != end; ++p)
- PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
- return true;
- }
-
- bool WriteInt64(int64_t i64) {
- char buffer[21];
- const char* end = internal::i64toa(i64, buffer);
- PutReserve(*os_, static_cast<size_t>(end - buffer));
- for (const char* p = buffer; p != end; ++p)
- PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
- return true;
- }
-
- bool WriteUint64(uint64_t u64) {
- char buffer[20];
- char* end = internal::u64toa(u64, buffer);
- PutReserve(*os_, static_cast<size_t>(end - buffer));
- for (char* p = buffer; p != end; ++p)
- PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
- return true;
- }
-
- bool WriteDouble(double d) {
- if (internal::Double(d).IsNanOrInf()) {
- if (!(writeFlags & kWriteNanAndInfFlag))
- return false;
- if (internal::Double(d).IsNan()) {
- PutReserve(*os_, 3);
- PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
- return true;
- }
- if (internal::Double(d).Sign()) {
- PutReserve(*os_, 9);
- PutUnsafe(*os_, '-');
- }
- else
- PutReserve(*os_, 8);
- PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
- PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
- return true;
- }
-
- char buffer[25];
- char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
- PutReserve(*os_, static_cast<size_t>(end - buffer));
- for (char* p = buffer; p != end; ++p)
- PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
- return true;
- }
-
- bool WriteString(const Ch* str, SizeType length) {
- static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- static const char escape[256] = {
-#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- //0 1 2 3 4 5 6 7 8 9 A B C D E F
- 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
- 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
- 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
- Z16, Z16, // 30~4F
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
- Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
-#undef Z16
- };
-
- if (TargetEncoding::supportUnicode)
- PutReserve(*os_, 2 + length * 6); // "\uxxxx..."
- else
- PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..."
-
- PutUnsafe(*os_, '\"');
- GenericStringStream<SourceEncoding> is(str);
- while (ScanWriteUnescapedString(is, length)) {
- const Ch c = is.Peek();
- if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
- // Unicode escaping
- unsigned codepoint;
- if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
- return false;
- PutUnsafe(*os_, '\\');
- PutUnsafe(*os_, 'u');
- if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
- PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]);
- PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]);
- PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]);
- PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
- }
- else {
- RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
- // Surrogate pair
- unsigned s = codepoint - 0x010000;
- unsigned lead = (s >> 10) + 0xD800;
- unsigned trail = (s & 0x3FF) + 0xDC00;
- PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]);
- PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]);
- PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]);
- PutUnsafe(*os_, hexDigits[(lead ) & 15]);
- PutUnsafe(*os_, '\\');
- PutUnsafe(*os_, 'u');
- PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]);
- PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]);
- PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]);
- PutUnsafe(*os_, hexDigits[(trail ) & 15]);
- }
- }
- else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
- is.Take();
- PutUnsafe(*os_, '\\');
- PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
- if (escape[static_cast<unsigned char>(c)] == 'u') {
- PutUnsafe(*os_, '0');
- PutUnsafe(*os_, '0');
- PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) >> 4]);
- PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
- }
- }
- else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
- Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
- Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
- return false;
- }
- PutUnsafe(*os_, '\"');
- return true;
- }
-
- bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
- return RAPIDJSON_LIKELY(is.Tell() < length);
- }
-
- bool WriteStartObject() { os_->Put('{'); return true; }
- bool WriteEndObject() { os_->Put('}'); return true; }
- bool WriteStartArray() { os_->Put('['); return true; }
- bool WriteEndArray() { os_->Put(']'); return true; }
-
- bool WriteRawValue(const Ch* json, size_t length) {
- PutReserve(*os_, length);
- for (size_t i = 0; i < length; i++) {
- RAPIDJSON_ASSERT(json[i] != '\0');
- PutUnsafe(*os_, json[i]);
- }
- return true;
- }
-
- void Prefix(Type type) {
- (void)type;
- if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
- Level* level = level_stack_.template Top<Level>();
- if (level->valueCount > 0) {
- if (level->inArray)
- os_->Put(','); // add comma if it is not the first element in array
- else // in object
- os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
- }
- if (!level->inArray && level->valueCount % 2 == 0)
- RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
- level->valueCount++;
- }
- else {
- RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
- hasRoot_ = true;
- }
- }
-
- // Flush the value if it is the top level one.
- bool EndValue(bool ret) {
- if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
- os_->Flush();
- return ret;
- }
-
- OutputStream* os_;
- internal::Stack<StackAllocator> level_stack_;
- int maxDecimalPlaces_;
- bool hasRoot_;
-
-private:
- // Prohibit copy constructor & assignment operator.
- Writer(const Writer&);
- Writer& operator=(const Writer&);
-};
-
-// Full specialization for StringStream to prevent memory copying
-
-template<>
-inline bool Writer<StringBuffer>::WriteInt(int i) {
- char *buffer = os_->Push(11);
- const char* end = internal::i32toa(i, buffer);
- os_->Pop(static_cast<size_t>(11 - (end - buffer)));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
- char *buffer = os_->Push(10);
- const char* end = internal::u32toa(u, buffer);
- os_->Pop(static_cast<size_t>(10 - (end - buffer)));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
- char *buffer = os_->Push(21);
- const char* end = internal::i64toa(i64, buffer);
- os_->Pop(static_cast<size_t>(21 - (end - buffer)));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
- char *buffer = os_->Push(20);
- const char* end = internal::u64toa(u, buffer);
- os_->Pop(static_cast<size_t>(20 - (end - buffer)));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteDouble(double d) {
- if (internal::Double(d).IsNanOrInf()) {
- // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
- if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
- return false;
- if (internal::Double(d).IsNan()) {
- PutReserve(*os_, 3);
- PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N');
- return true;
- }
- if (internal::Double(d).Sign()) {
- PutReserve(*os_, 9);
- PutUnsafe(*os_, '-');
- }
- else
- PutReserve(*os_, 8);
- PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f');
- PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y');
- return true;
- }
-
- char *buffer = os_->Push(25);
- char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
- os_->Pop(static_cast<size_t>(25 - (end - buffer)));
- return true;
-}
-
-#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
-template<>
-inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
- if (length < 16)
- return RAPIDJSON_LIKELY(is.Tell() < length);
-
- if (!RAPIDJSON_LIKELY(is.Tell() < length))
- return false;
-
- const char* p = is.src_;
- const char* end = is.head_ + length;
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
- const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
- if (nextAligned > end)
- return true;
-
- while (p != nextAligned)
- if (*p < 0x20 || *p == '\"' || *p == '\\') {
- is.src_ = p;
- return RAPIDJSON_LIKELY(is.Tell() < length);
- }
- else
- os_->PutUnsafe(*p++);
-
- // The rest of string using SIMD
- static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
- static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
- static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
- const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
- const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
- const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
-
- for (; p != endAligned; p += 16) {
- const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
- const __m128i t1 = _mm_cmpeq_epi8(s, dq);
- const __m128i t2 = _mm_cmpeq_epi8(s, bs);
- const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
- const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
- unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
- if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
- SizeType len;
-#ifdef _MSC_VER // Find the index of first escaped
- unsigned long offset;
- _BitScanForward(&offset, r);
- len = offset;
-#else
- len = static_cast<SizeType>(__builtin_ffs(r) - 1);
-#endif
- char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
- for (size_t i = 0; i < len; i++)
- q[i] = p[i];
-
- p += len;
- break;
- }
- _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s);
- }
-
- is.src_ = p;
- return RAPIDJSON_LIKELY(is.Tell() < length);
-}
-#endif // defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef __clang__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_RAPIDJSON_H_
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: Arg.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno .
- * Copyright (c) 2017 Google Inc.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_ARGUMENT_H
-#define TCLAP_ARGUMENT_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <iomanip>
-#include <cstdio>
-
-#include <tclap/sstream.h>
-
-#if defined(HAVE_SSTREAM)
-#include <sstream>
-typedef std::istringstream istringstream;
-#elif defined(HAVE_STRSTREAM)
-#include <strstream>
-typedef std::istrstream istringstream;
-#else
-#error "Need a stringstream (sstream or strstream) to compile!"
-#endif
-
-#include <tclap/ArgException.h>
-#include <tclap/Visitor.h>
-#include <tclap/CmdLineInterface.h>
-#include <tclap/ArgTraits.h>
-#include <tclap/StandardTraits.h>
-
-namespace TCLAP {
-
-/**
- * A virtual base class that defines the essential data for all arguments.
- * This class, or one of its existing children, must be subclassed to do
- * anything.
- */
-class Arg
-{
- private:
- /**
- * Prevent accidental copying.
- */
- Arg(const Arg& rhs);
-
- /**
- * Prevent accidental copying.
- */
- Arg& operator=(const Arg& rhs);
-
- /**
- * Indicates whether the rest of the arguments should be ignored.
- */
- static bool& ignoreRestRef() { static bool ign = false; return ign; }
-
- /**
- * The delimiter that separates an argument flag/name from the
- * value.
- */
- static char& delimiterRef() { static char delim = ' '; return delim; }
-
- protected:
-
- /**
- * The single char flag used to identify the argument.
- * This value (preceded by a dash {-}), can be used to identify
- * an argument on the command line. The _flag can be blank,
- * in fact this is how unlabeled args work. Unlabeled args must
- * override appropriate functions to get correct handling. Note
- * that the _flag does NOT include the dash as part of the flag.
- */
- std::string _flag;
-
- /**
- * A single word namd identifying the argument.
- * This value (preceded by two dashed {--}) can also be used
- * to identify an argument on the command line. Note that the
- * _name does NOT include the two dashes as part of the _name. The
- * _name cannot be blank.
- */
- std::string _name;
-
- /**
- * Description of the argument.
- */
- std::string _description;
-
- /**
- * Indicating whether the argument is required.
- */
- bool _required;
-
- /**
- * Label to be used in usage description. Normally set to
- * "required", but can be changed when necessary.
- */
- std::string _requireLabel;
-
- /**
- * Indicates whether a value is required for the argument.
- * Note that the value may be required but the argument/value
- * combination may not be, as specified by _required.
- */
- bool _valueRequired;
-
- /**
- * Indicates whether the argument has been set.
- * Indicates that a value on the command line has matched the
- * name/flag of this argument and the values have been set accordingly.
- */
- bool _alreadySet;
-
- /**
- * A pointer to a visitor object.
- * The visitor allows special handling to occur as soon as the
- * argument is matched. This defaults to NULL and should not
- * be used unless absolutely necessary.
- */
- Visitor* _visitor;
-
- /**
- * Whether this argument can be ignored, if desired.
- */
- bool _ignoreable;
-
- /**
- * Indicates that the arg was set as part of an XOR and not on the
- * command line.
- */
- bool _xorSet;
-
- bool _acceptsMultipleValues;
-
- /**
- * Performs the special handling described by the Visitor.
- */
- void _checkWithVisitor() const;
-
- /**
- * Primary constructor. YOU (yes you) should NEVER construct an Arg
- * directly, this is a base class that is extended by various children
- * that are meant to be used. Use SwitchArg, ValueArg, MultiArg,
- * UnlabeledValueArg, or UnlabeledMultiArg instead.
- *
- * \param flag - The flag identifying the argument.
- * \param name - The name identifying the argument.
- * \param desc - The description of the argument, used in the usage.
- * \param req - Whether the argument is required.
- * \param valreq - Whether the a value is required for the argument.
- * \param v - The visitor checked by the argument. Defaults to NULL.
- */
- Arg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- bool valreq,
- Visitor* v = NULL );
-
- public:
- /**
- * Destructor.
- */
- virtual ~Arg();
-
- /**
- * Adds this to the specified list of Args.
- * \param argList - The list to add this to.
- */
- virtual void addToList( std::list<Arg*>& argList ) const;
-
- /**
- * Begin ignoring arguments since the "--" argument was specified.
- */
- static void beginIgnoring() { ignoreRestRef() = true; }
-
- /**
- * Whether to ignore the rest.
- */
- static bool ignoreRest() { return ignoreRestRef(); }
-
- /**
- * The delimiter that separates an argument flag/name from the
- * value.
- */
- static char delimiter() { return delimiterRef(); }
-
- /**
- * The char used as a place holder when SwitchArgs are combined.
- * Currently set to the bell char (ASCII 7).
- */
- static char blankChar() { return (char)7; }
-
- /**
- * The char that indicates the beginning of a flag. Defaults to '-', but
- * clients can define TCLAP_FLAGSTARTCHAR to override.
- */
-#ifndef TCLAP_FLAGSTARTCHAR
-#define TCLAP_FLAGSTARTCHAR '-'
-#endif
- static char flagStartChar() { return TCLAP_FLAGSTARTCHAR; }
-
- /**
- * The sting that indicates the beginning of a flag. Defaults to "-", but
- * clients can define TCLAP_FLAGSTARTSTRING to override. Should be the same
- * as TCLAP_FLAGSTARTCHAR.
- */
-#ifndef TCLAP_FLAGSTARTSTRING
-#define TCLAP_FLAGSTARTSTRING "-"
-#endif
- static const std::string flagStartString() { return TCLAP_FLAGSTARTSTRING; }
-
- /**
- * The sting that indicates the beginning of a name. Defaults to "--", but
- * clients can define TCLAP_NAMESTARTSTRING to override.
- */
-#ifndef TCLAP_NAMESTARTSTRING
-#define TCLAP_NAMESTARTSTRING "--"
-#endif
- static const std::string nameStartString() { return TCLAP_NAMESTARTSTRING; }
-
- /**
- * The name used to identify the ignore rest argument.
- */
- static const std::string ignoreNameString() { return "ignore_rest"; }
-
- /**
- * Sets the delimiter for all arguments.
- * \param c - The character that delimits flags/names from values.
- */
- static void setDelimiter( char c ) { delimiterRef() = c; }
-
- /**
- * Pure virtual method meant to handle the parsing and value assignment
- * of the string on the command line.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings. What is
- * passed in from main.
- */
- virtual bool processArg(int *i, std::vector<std::string>& args) = 0;
-
- /**
- * Operator ==.
- * Equality operator. Must be virtual to handle unlabeled args.
- * \param a - The Arg to be compared to this.
- */
- virtual bool operator==(const Arg& a) const;
-
- /**
- * Returns the argument flag.
- */
- const std::string& getFlag() const;
-
- /**
- * Returns the argument name.
- */
- const std::string& getName() const;
-
- /**
- * Returns the argument description.
- */
- std::string getDescription() const;
-
- /**
- * Indicates whether the argument is required.
- */
- virtual bool isRequired() const;
-
- /**
- * Sets _required to true. This is used by the XorHandler.
- * You really have no reason to ever use it.
- */
- void forceRequired();
-
- /**
- * Sets the _alreadySet value to true. This is used by the XorHandler.
- * You really have no reason to ever use it.
- */
- void xorSet();
-
- /**
- * Indicates whether a value must be specified for argument.
- */
- bool isValueRequired() const;
-
- /**
- * Indicates whether the argument has already been set. Only true
- * if the arg has been matched on the command line.
- */
- bool isSet() const;
-
- /**
- * Indicates whether the argument can be ignored, if desired.
- */
- bool isIgnoreable() const;
-
- /**
- * A method that tests whether a string matches this argument.
- * This is generally called by the processArg() method. This
- * method could be re-implemented by a child to change how
- * arguments are specified on the command line.
- * \param s - The string to be compared to the flag/name to determine
- * whether the arg matches.
- */
- virtual bool argMatches( const std::string& s ) const;
-
- /**
- * Returns a simple string representation of the argument.
- * Primarily for debugging.
- */
- virtual std::string toString() const;
-
- /**
- * Returns a short ID for the usage.
- * \param valueId - The value used in the id.
- */
- virtual std::string shortID( const std::string& valueId = "val" ) const;
-
- /**
- * Returns a long ID for the usage.
- * \param valueId - The value used in the id.
- */
- virtual std::string longID( const std::string& valueId = "val" ) const;
-
- /**
- * Trims a value off of the flag.
- * \param flag - The string from which the flag and value will be
- * trimmed. Contains the flag once the value has been trimmed.
- * \param value - Where the value trimmed from the string will
- * be stored.
- */
- virtual void trimFlag( std::string& flag, std::string& value ) const;
-
- /**
- * Checks whether a given string has blank chars, indicating that
- * it is a combined SwitchArg. If so, return true, otherwise return
- * false.
- * \param s - string to be checked.
- */
- bool _hasBlanks( const std::string& s ) const;
-
- /**
- * Sets the requireLabel. Used by XorHandler. You shouldn't ever
- * use this.
- * \param s - Set the requireLabel to this value.
- */
- void setRequireLabel( const std::string& s );
-
- /**
- * Used for MultiArgs and XorHandler to determine whether args
- * can still be set.
- */
- virtual bool allowMore();
-
- /**
- * Use by output classes to determine whether an Arg accepts
- * multiple values.
- */
- virtual bool acceptsMultipleValues();
-
- /**
- * Clears the Arg object and allows it to be reused by new
- * command lines.
- */
- virtual void reset();
-};
-
-/**
- * Typedef of an Arg list iterator.
- */
-typedef std::list<Arg*>::iterator ArgListIterator;
-
-/**
- * Typedef of an Arg vector iterator.
- */
-typedef std::vector<Arg*>::iterator ArgVectorIterator;
-
-/**
- * Typedef of a Visitor list iterator.
- */
-typedef std::list<Visitor*>::iterator VisitorListIterator;
-
-/*
- * Extract a value of type T from it's string representation contained
- * in strVal. The ValueLike parameter used to select the correct
- * specialization of ExtractValue depending on the value traits of T.
- * ValueLike traits use operator>> to assign the value from strVal.
- */
-template<typename T> void
-ExtractValue(T &destVal, const std::string& strVal, ValueLike vl)
-{
- static_cast<void>(vl); // Avoid warning about unused vl
- istringstream is(strVal.c_str());
-
- int valuesRead = 0;
- while ( is.good() ) {
- if ( is.peek() != EOF )
-#ifdef TCLAP_SETBASE_ZERO
- is >> std::setbase(0) >> destVal;
-#else
- is >> destVal;
-#endif
- else
- break;
-
- valuesRead++;
- }
-
- if ( is.fail() )
- throw( ArgParseException("Couldn't read argument value "
- "from string '" + strVal + "'"));
-
-
- if ( valuesRead > 1 )
- throw( ArgParseException("More than one valid value parsed from "
- "string '" + strVal + "'"));
-
-}
-
-/*
- * Extract a value of type T from it's string representation contained
- * in strVal. The ValueLike parameter used to select the correct
- * specialization of ExtractValue depending on the value traits of T.
- * StringLike uses assignment (operator=) to assign from strVal.
- */
-template<typename T> void
-ExtractValue(T &destVal, const std::string& strVal, StringLike sl)
-{
- static_cast<void>(sl); // Avoid warning about unused sl
- SetString(destVal, strVal);
-}
-
-//////////////////////////////////////////////////////////////////////
-//BEGIN Arg.cpp
-//////////////////////////////////////////////////////////////////////
-
-inline Arg::Arg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- bool valreq,
- Visitor* v) :
- _flag(flag),
- _name(name),
- _description(desc),
- _required(req),
- _requireLabel("required"),
- _valueRequired(valreq),
- _alreadySet(false),
- _visitor( v ),
- _ignoreable(true),
- _xorSet(false),
- _acceptsMultipleValues(false)
-{
- if ( _flag.length() > 1 )
- throw(SpecificationException(
- "Argument flag can only be one character long", toString() ) );
-
- if ( _name != ignoreNameString() &&
- ( _flag == Arg::flagStartString() ||
- _flag == Arg::nameStartString() ||
- _flag == " " ) )
- throw(SpecificationException("Argument flag cannot be either '" +
- Arg::flagStartString() + "' or '" +
- Arg::nameStartString() + "' or a space.",
- toString() ) );
-
- if ( ( _name.substr( 0, Arg::flagStartString().length() ) == Arg::flagStartString() ) ||
- ( _name.substr( 0, Arg::nameStartString().length() ) == Arg::nameStartString() ) ||
- ( _name.find( " ", 0 ) != std::string::npos ) )
- throw(SpecificationException("Argument name begin with either '" +
- Arg::flagStartString() + "' or '" +
- Arg::nameStartString() + "' or space.",
- toString() ) );
-
-}
-
-inline Arg::~Arg() { }
-
-inline std::string Arg::shortID( const std::string& valueId ) const
-{
- std::string id = "";
-
- if ( _flag != "" )
- id = Arg::flagStartString() + _flag;
- else
- id = Arg::nameStartString() + _name;
-
- if ( _valueRequired )
- id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
-
- if ( !_required )
- id = "[" + id + "]";
-
- return id;
-}
-
-inline std::string Arg::longID( const std::string& valueId ) const
-{
- std::string id = "";
-
- if ( _flag != "" )
- {
- id += Arg::flagStartString() + _flag;
-
- if ( _valueRequired )
- id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
-
- id += ", ";
- }
-
- id += Arg::nameStartString() + _name;
-
- if ( _valueRequired )
- id += std::string( 1, Arg::delimiter() ) + "<" + valueId + ">";
-
- return id;
-
-}
-
-inline bool Arg::operator==(const Arg& a) const
-{
- if ( ( _flag != "" && _flag == a._flag ) || _name == a._name)
- return true;
- else
- return false;
-}
-
-inline std::string Arg::getDescription() const
-{
- std::string desc = "";
- if ( _required )
- desc = "(" + _requireLabel + ") ";
-
-// if ( _valueRequired )
-// desc += "(value required) ";
-
- desc += _description;
- return desc;
-}
-
-inline const std::string& Arg::getFlag() const { return _flag; }
-
-inline const std::string& Arg::getName() const { return _name; }
-
-inline bool Arg::isRequired() const { return _required; }
-
-inline bool Arg::isValueRequired() const { return _valueRequired; }
-
-inline bool Arg::isSet() const
-{
- if ( _alreadySet && !_xorSet )
- return true;
- else
- return false;
-}
-
-inline bool Arg::isIgnoreable() const { return _ignoreable; }
-
-inline void Arg::setRequireLabel( const std::string& s)
-{
- _requireLabel = s;
-}
-
-inline bool Arg::argMatches( const std::string& argFlag ) const
-{
- if ( ( argFlag == Arg::flagStartString() + _flag && _flag != "" ) ||
- argFlag == Arg::nameStartString() + _name )
- return true;
- else
- return false;
-}
-
-inline std::string Arg::toString() const
-{
- std::string s = "";
-
- if ( _flag != "" )
- s += Arg::flagStartString() + _flag + " ";
-
- s += "(" + Arg::nameStartString() + _name + ")";
-
- return s;
-}
-
-inline void Arg::_checkWithVisitor() const
-{
- if ( _visitor != NULL )
- _visitor->visit();
-}
-
-/**
- * Implementation of trimFlag.
- */
-inline void Arg::trimFlag(std::string& flag, std::string& value) const
-{
- int stop = 0;
- for ( int i = 0; static_cast<unsigned int>(i) < flag.length(); i++ )
- if ( flag[i] == Arg::delimiter() )
- {
- stop = i;
- break;
- }
-
- if ( stop > 1 )
- {
- value = flag.substr(stop+1);
- flag = flag.substr(0,stop);
- }
-
-}
-
-/**
- * Implementation of _hasBlanks.
- */
-inline bool Arg::_hasBlanks( const std::string& s ) const
-{
- for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
- if ( s[i] == Arg::blankChar() )
- return true;
-
- return false;
-}
-
-inline void Arg::forceRequired()
-{
- _required = true;
-}
-
-inline void Arg::xorSet()
-{
- _alreadySet = true;
- _xorSet = true;
-}
-
-/**
- * Overridden by Args that need to added to the end of the list.
- */
-inline void Arg::addToList( std::list<Arg*>& argList ) const
-{
- argList.push_front( const_cast<Arg*>(this) );
-}
-
-inline bool Arg::allowMore()
-{
- return false;
-}
-
-inline bool Arg::acceptsMultipleValues()
-{
- return _acceptsMultipleValues;
-}
-
-inline void Arg::reset()
-{
- _xorSet = false;
- _alreadySet = false;
-}
-
-//////////////////////////////////////////////////////////////////////
-//END Arg.cpp
-//////////////////////////////////////////////////////////////////////
-
-} //namespace TCLAP
-
-#endif
-
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: ArgException.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_ARG_EXCEPTION_H
-#define TCLAP_ARG_EXCEPTION_H
-
-#include <string>
-#include <exception>
-
-namespace TCLAP {
-
-/**
- * A simple class that defines and argument exception. Should be caught
- * whenever a CmdLine is created and parsed.
- */
-class ArgException : public std::exception
-{
- public:
-
- /**
- * Constructor.
- * \param text - The text of the exception.
- * \param id - The text identifying the argument source.
- * \param td - Text describing the type of ArgException it is.
- * of the exception.
- */
- ArgException( const std::string& text = "undefined exception",
- const std::string& id = "undefined",
- const std::string& td = "Generic ArgException")
- : std::exception(),
- _errorText(text),
- _argId( id ),
- _typeDescription(td)
- { }
-
- /**
- * Destructor.
- */
- virtual ~ArgException() throw() { }
-
- /**
- * Returns the error text.
- */
- std::string error() const { return ( _errorText ); }
-
- /**
- * Returns the argument id.
- */
- std::string argId() const
- {
- if ( _argId == "undefined" )
- return " ";
- else
- return ( "Argument: " + _argId );
- }
-
- /**
- * Returns the arg id and error text.
- */
- const char* what() const throw()
- {
- static std::string ex;
- ex = _argId + " -- " + _errorText;
- return ex.c_str();
- }
-
- /**
- * Returns the type of the exception. Used to explain and distinguish
- * between different child exceptions.
- */
- std::string typeDescription() const
- {
- return _typeDescription;
- }
-
-
- private:
-
- /**
- * The text of the exception message.
- */
- std::string _errorText;
-
- /**
- * The argument related to this exception.
- */
- std::string _argId;
-
- /**
- * Describes the type of the exception. Used to distinguish
- * between different child exceptions.
- */
- std::string _typeDescription;
-
-};
-
-/**
- * Thrown from within the child Arg classes when it fails to properly
- * parse the argument it has been passed.
- */
-class ArgParseException : public ArgException
-{
- public:
- /**
- * Constructor.
- * \param text - The text of the exception.
- * \param id - The text identifying the argument source
- * of the exception.
- */
- ArgParseException( const std::string& text = "undefined exception",
- const std::string& id = "undefined" )
- : ArgException( text,
- id,
- std::string( "Exception found while parsing " ) +
- std::string( "the value the Arg has been passed." ))
- { }
-};
-
-/**
- * Thrown from CmdLine when the arguments on the command line are not
- * properly specified, e.g. too many arguments, required argument missing, etc.
- */
-class CmdLineParseException : public ArgException
-{
- public:
- /**
- * Constructor.
- * \param text - The text of the exception.
- * \param id - The text identifying the argument source
- * of the exception.
- */
- CmdLineParseException( const std::string& text = "undefined exception",
- const std::string& id = "undefined" )
- : ArgException( text,
- id,
- std::string( "Exception found when the values ") +
- std::string( "on the command line do not meet ") +
- std::string( "the requirements of the defined ") +
- std::string( "Args." ))
- { }
-};
-
-/**
- * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g.
- * same flag as another Arg, same name, etc.
- */
-class SpecificationException : public ArgException
-{
- public:
- /**
- * Constructor.
- * \param text - The text of the exception.
- * \param id - The text identifying the argument source
- * of the exception.
- */
- SpecificationException( const std::string& text = "undefined exception",
- const std::string& id = "undefined" )
- : ArgException( text,
- id,
- std::string("Exception found when an Arg object ")+
- std::string("is improperly defined by the ") +
- std::string("developer." ))
- { }
-
-};
-
-class ExitException {
-public:
- ExitException(int estat) : _estat(estat) {}
-
- int getExitStatus() const { return _estat; }
-
-private:
- int _estat;
-};
-
-} // namespace TCLAP
-
-#endif
-
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: ArgTraits.h
- *
- * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-// This is an internal tclap file, you should probably not have to
-// include this directly
-
-#ifndef TCLAP_ARGTRAITS_H
-#define TCLAP_ARGTRAITS_H
-
-namespace TCLAP {
-
-// We use two empty structs to get compile type specialization
-// function to work
-
-/**
- * A value like argument value type is a value that can be set using
- * operator>>. This is the default value type.
- */
-struct ValueLike {
- typedef ValueLike ValueCategory;
- virtual ~ValueLike() {}
-};
-
-/**
- * A string like argument value type is a value that can be set using
- * operator=(string). Useful if the value type contains spaces which
- * will be broken up into individual tokens by operator>>.
- */
-struct StringLike {
- virtual ~StringLike() {}
-};
-
-/**
- * A class can inherit from this object to make it have string like
- * traits. This is a compile time thing and does not add any overhead
- * to the inherenting class.
- */
-struct StringLikeTrait {
- typedef StringLike ValueCategory;
- virtual ~StringLikeTrait() {}
-};
-
-/**
- * A class can inherit from this object to make it have value like
- * traits. This is a compile time thing and does not add any overhead
- * to the inherenting class.
- */
-struct ValueLikeTrait {
- typedef ValueLike ValueCategory;
- virtual ~ValueLikeTrait() {}
-};
-
-/**
- * Arg traits are used to get compile type specialization when parsing
- * argument values. Using an ArgTraits you can specify the way that
- * values gets assigned to any particular type during parsing. The two
- * supported types are StringLike and ValueLike.
- */
-template<typename T>
-struct ArgTraits {
- typedef typename T::ValueCategory ValueCategory;
- virtual ~ArgTraits() {}
- //typedef ValueLike ValueCategory;
-};
-
-} // namespace
-
-#endif
-
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: CmdLine.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_CMDLINE_H
-#define TCLAP_CMDLINE_H
-
-#include <tclap/SwitchArg.h>
-#include <tclap/MultiSwitchArg.h>
-#include <tclap/UnlabeledValueArg.h>
-#include <tclap/UnlabeledMultiArg.h>
-
-#include <tclap/XorHandler.h>
-#include <tclap/HelpVisitor.h>
-#include <tclap/VersionVisitor.h>
-#include <tclap/IgnoreRestVisitor.h>
-
-#include <tclap/CmdLineOutput.h>
-#include <tclap/StdOutput.h>
-
-#include <tclap/Constraint.h>
-#include <tclap/ValuesConstraint.h>
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <iomanip>
-#include <algorithm>
-#include <stdlib.h> // Needed for exit(), which isn't defined in some envs.
-
-namespace TCLAP {
-
-template<typename T> void DelPtr(T ptr)
-{
- delete ptr;
-}
-
-template<typename C> void ClearContainer(C &c)
-{
- typedef typename C::value_type value_type;
- std::for_each(c.begin(), c.end(), DelPtr<value_type>);
- c.clear();
-}
-
-
-/**
- * The base class that manages the command line definition and passes
- * along the parsing to the appropriate Arg classes.
- */
-class CmdLine : public CmdLineInterface
-{
- protected:
-
- /**
- * The list of arguments that will be tested against the
- * command line.
- */
- std::list<Arg*> _argList;
-
- /**
- * The name of the program. Set to argv[0].
- */
- std::string _progName;
-
- /**
- * A message used to describe the program. Used in the usage output.
- */
- std::string _message;
-
- /**
- * The version to be displayed with the --version switch.
- */
- std::string _version;
-
- /**
- * The number of arguments that are required to be present on
- * the command line. This is set dynamically, based on the
- * Args added to the CmdLine object.
- */
- int _numRequired;
-
- /**
- * The character that is used to separate the argument flag/name
- * from the value. Defaults to ' ' (space).
- */
- char _delimiter;
-
- /**
- * The handler that manages xoring lists of args.
- */
- XorHandler _xorHandler;
-
- /**
- * A list of Args to be explicitly deleted when the destructor
- * is called. At the moment, this only includes the three default
- * Args.
- */
- std::list<Arg*> _argDeleteOnExitList;
-
- /**
- * A list of Visitors to be explicitly deleted when the destructor
- * is called. At the moment, these are the Visitors created for the
- * default Args.
- */
- std::list<Visitor*> _visitorDeleteOnExitList;
-
- /**
- * Object that handles all output for the CmdLine.
- */
- CmdLineOutput* _output;
-
- /**
- * Should CmdLine handle parsing exceptions internally?
- */
- bool _handleExceptions;
-
- /**
- * Throws an exception listing the missing args.
- */
- void missingArgsException();
-
- /**
- * Checks whether a name/flag string matches entirely matches
- * the Arg::blankChar. Used when multiple switches are combined
- * into a single argument.
- * \param s - The message to be used in the usage.
- */
- bool _emptyCombined(const std::string& s);
-
- /**
- * Perform a delete ptr; operation on ptr when this object is deleted.
- */
- void deleteOnExit(Arg* ptr);
-
- /**
- * Perform a delete ptr; operation on ptr when this object is deleted.
- */
- void deleteOnExit(Visitor* ptr);
-
-private:
-
- /**
- * Prevent accidental copying.
- */
- CmdLine(const CmdLine& rhs);
- CmdLine& operator=(const CmdLine& rhs);
-
- /**
- * Encapsulates the code common to the constructors
- * (which is all of it).
- */
- void _constructor();
-
-
- /**
- * Is set to true when a user sets the output object. We use this so
- * that we don't delete objects that are created outside of this lib.
- */
- bool _userSetOutput;
-
- /**
- * Whether or not to automatically create help and version switches.
- */
- bool _helpAndVersion;
-
- public:
-
- /**
- * Command line constructor. Defines how the arguments will be
- * parsed.
- * \param message - The message to be used in the usage
- * output.
- * \param delimiter - The character that is used to separate
- * the argument flag/name from the value. Defaults to ' ' (space).
- * \param version - The version number to be used in the
- * --version switch.
- * \param helpAndVersion - Whether or not to create the Help and
- * Version switches. Defaults to true.
- */
- CmdLine(const std::string& message,
- const char delimiter = ' ',
- const std::string& version = "none",
- bool helpAndVersion = true);
-
- /**
- * Deletes any resources allocated by a CmdLine object.
- */
- virtual ~CmdLine();
-
- /**
- * Adds an argument to the list of arguments to be parsed.
- * \param a - Argument to be added.
- */
- void add( Arg& a );
-
- /**
- * An alternative add. Functionally identical.
- * \param a - Argument to be added.
- */
- void add( Arg* a );
-
- /**
- * Add two Args that will be xor'd. If this method is used, add does
- * not need to be called.
- * \param a - Argument to be added and xor'd.
- * \param b - Argument to be added and xor'd.
- */
- void xorAdd( Arg& a, Arg& b );
-
- /**
- * Add a list of Args that will be xor'd. If this method is used,
- * add does not need to be called.
- * \param xors - List of Args to be added and xor'd.
- */
- void xorAdd( std::vector<Arg*>& xors );
-
- /**
- * Parses the command line.
- * \param argc - Number of arguments.
- * \param argv - Array of arguments.
- */
- void parse(int argc, const char * const * argv);
-
- /**
- * Parses the command line.
- * \param args - A vector of strings representing the args.
- * args[0] is still the program name.
- */
- void parse(std::vector<std::string>& args);
-
- /**
- *
- */
- CmdLineOutput* getOutput();
-
- /**
- *
- */
- void setOutput(CmdLineOutput* co);
-
- /**
- *
- */
- std::string& getVersion();
-
- /**
- *
- */
- std::string& getProgramName();
-
- /**
- *
- */
- std::list<Arg*>& getArgList();
-
- /**
- *
- */
- XorHandler& getXorHandler();
-
- /**
- *
- */
- char getDelimiter();
-
- /**
- *
- */
- std::string& getMessage();
-
- /**
- *
- */
- bool hasHelpAndVersion();
-
- /**
- * Disables or enables CmdLine's internal parsing exception handling.
- *
- * @param state Should CmdLine handle parsing exceptions internally?
- */
- void setExceptionHandling(const bool state);
-
- /**
- * Returns the current state of the internal exception handling.
- *
- * @retval true Parsing exceptions are handled internally.
- * @retval false Parsing exceptions are propagated to the caller.
- */
- bool getExceptionHandling() const;
-
- /**
- * Allows the CmdLine object to be reused.
- */
- void reset();
-
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-//Begin CmdLine.cpp
-///////////////////////////////////////////////////////////////////////////////
-
-inline CmdLine::CmdLine(const std::string& m,
- char delim,
- const std::string& v,
- bool help )
- :
- _argList(std::list<Arg*>()),
- _progName("not_set_yet"),
- _message(m),
- _version(v),
- _numRequired(0),
- _delimiter(delim),
- _xorHandler(XorHandler()),
- _argDeleteOnExitList(std::list<Arg*>()),
- _visitorDeleteOnExitList(std::list<Visitor*>()),
- _output(0),
- _handleExceptions(true),
- _userSetOutput(false),
- _helpAndVersion(help)
-{
- _constructor();
-}
-
-inline CmdLine::~CmdLine()
-{
- ClearContainer(_argDeleteOnExitList);
- ClearContainer(_visitorDeleteOnExitList);
-
- if ( !_userSetOutput ) {
- delete _output;
- _output = 0;
- }
-}
-
-inline void CmdLine::_constructor()
-{
- _output = new StdOutput;
-
- Arg::setDelimiter( _delimiter );
-
- Visitor* v;
-
- if ( _helpAndVersion )
- {
- v = new HelpVisitor( this, &_output );
- SwitchArg* help = new SwitchArg("h","help",
- "Displays usage information and exits.",
- false, v);
- add( help );
- deleteOnExit(help);
- deleteOnExit(v);
-
- v = new VersionVisitor( this, &_output );
- SwitchArg* vers = new SwitchArg("","version",
- "Displays version information and exits.",
- false, v);
- add( vers );
- deleteOnExit(vers);
- deleteOnExit(v);
- }
-
- v = new IgnoreRestVisitor();
- SwitchArg* ignore = new SwitchArg(Arg::flagStartString(),
- Arg::ignoreNameString(),
- "Ignores the rest of the labeled arguments following this flag.",
- false, v);
- add( ignore );
- deleteOnExit(ignore);
- deleteOnExit(v);
-}
-
-inline void CmdLine::xorAdd( std::vector<Arg*>& ors )
-{
- _xorHandler.add( ors );
-
- for (ArgVectorIterator it = ors.begin(); it != ors.end(); it++)
- {
- (*it)->forceRequired();
- (*it)->setRequireLabel( "OR required" );
- add( *it );
- }
-}
-
-inline void CmdLine::xorAdd( Arg& a, Arg& b )
-{
- std::vector<Arg*> ors;
- ors.push_back( &a );
- ors.push_back( &b );
- xorAdd( ors );
-}
-
-inline void CmdLine::add( Arg& a )
-{
- add( &a );
-}
-
-inline void CmdLine::add( Arg* a )
-{
- for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
- if ( *a == *(*it) )
- throw( SpecificationException(
- "Argument with same flag/name already exists!",
- a->longID() ) );
-
- a->addToList( _argList );
-
- if ( a->isRequired() )
- _numRequired++;
-}
-
-
-inline void CmdLine::parse(int argc, const char * const * argv)
-{
- // this step is necessary so that we have easy access to
- // mutable strings.
- std::vector<std::string> args;
- for (int i = 0; i < argc; i++)
- args.push_back(argv[i]);
-
- parse(args);
-}
-
-inline void CmdLine::parse(std::vector<std::string>& args)
-{
- bool shouldExit = false;
- int estat = 0;
-
- try {
- _progName = args.front();
- args.erase(args.begin());
-
- int requiredCount = 0;
-
- for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
- {
- bool matched = false;
- for (ArgListIterator it = _argList.begin();
- it != _argList.end(); it++) {
- if ( (*it)->processArg( &i, args ) )
- {
- requiredCount += _xorHandler.check( *it );
- matched = true;
- break;
- }
- }
-
- // checks to see if the argument is an empty combined
- // switch and if so, then we've actually matched it
- if ( !matched && _emptyCombined( args[i] ) )
- matched = true;
-
- if ( !matched && !Arg::ignoreRest() )
- throw(CmdLineParseException("Couldn't find match "
- "for argument",
- args[i]));
- }
-
- if ( requiredCount < _numRequired )
- missingArgsException();
-
- if ( requiredCount > _numRequired )
- throw(CmdLineParseException("Too many arguments!"));
-
- } catch ( ArgException& e ) {
- // If we're not handling the exceptions, rethrow.
- if ( !_handleExceptions) {
- throw;
- }
-
- try {
- _output->failure(*this,e);
- } catch ( ExitException &ee ) {
- estat = ee.getExitStatus();
- shouldExit = true;
- }
- } catch (ExitException &ee) {
- // If we're not handling the exceptions, rethrow.
- if ( !_handleExceptions) {
- throw;
- }
-
- estat = ee.getExitStatus();
- shouldExit = true;
- }
-
- if (shouldExit)
- exit(estat);
-}
-
-inline bool CmdLine::_emptyCombined(const std::string& s)
-{
- if ( s.length() > 0 && s[0] != Arg::flagStartChar() )
- return false;
-
- for ( int i = 1; static_cast<unsigned int>(i) < s.length(); i++ )
- if ( s[i] != Arg::blankChar() )
- return false;
-
- return true;
-}
-
-inline void CmdLine::missingArgsException()
-{
- int count = 0;
-
- std::string missingArgList;
- for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
- {
- if ( (*it)->isRequired() && !(*it)->isSet() )
- {
- missingArgList += (*it)->getName();
- missingArgList += ", ";
- count++;
- }
- }
- missingArgList = missingArgList.substr(0,missingArgList.length()-2);
-
- std::string msg;
- if ( count > 1 )
- msg = "Required arguments missing: ";
- else
- msg = "Required argument missing: ";
-
- msg += missingArgList;
-
- throw(CmdLineParseException(msg));
-}
-
-inline void CmdLine::deleteOnExit(Arg* ptr)
-{
- _argDeleteOnExitList.push_back(ptr);
-}
-
-inline void CmdLine::deleteOnExit(Visitor* ptr)
-{
- _visitorDeleteOnExitList.push_back(ptr);
-}
-
-inline CmdLineOutput* CmdLine::getOutput()
-{
- return _output;
-}
-
-inline void CmdLine::setOutput(CmdLineOutput* co)
-{
- if ( !_userSetOutput )
- delete _output;
- _userSetOutput = true;
- _output = co;
-}
-
-inline std::string& CmdLine::getVersion()
-{
- return _version;
-}
-
-inline std::string& CmdLine::getProgramName()
-{
- return _progName;
-}
-
-inline std::list<Arg*>& CmdLine::getArgList()
-{
- return _argList;
-}
-
-inline XorHandler& CmdLine::getXorHandler()
-{
- return _xorHandler;
-}
-
-inline char CmdLine::getDelimiter()
-{
- return _delimiter;
-}
-
-inline std::string& CmdLine::getMessage()
-{
- return _message;
-}
-
-inline bool CmdLine::hasHelpAndVersion()
-{
- return _helpAndVersion;
-}
-
-inline void CmdLine::setExceptionHandling(const bool state)
-{
- _handleExceptions = state;
-}
-
-inline bool CmdLine::getExceptionHandling() const
-{
- return _handleExceptions;
-}
-
-inline void CmdLine::reset()
-{
- for( ArgListIterator it = _argList.begin(); it != _argList.end(); it++ )
- (*it)->reset();
-
- _progName.clear();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//End CmdLine.cpp
-///////////////////////////////////////////////////////////////////////////////
-
-
-
-} //namespace TCLAP
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: CmdLineInterface.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_COMMANDLINE_INTERFACE_H
-#define TCLAP_COMMANDLINE_INTERFACE_H
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <algorithm>
-
-
-namespace TCLAP {
-
-class Arg;
-class CmdLineOutput;
-class XorHandler;
-
-/**
- * The base class that manages the command line definition and passes
- * along the parsing to the appropriate Arg classes.
- */
-class CmdLineInterface
-{
- public:
-
- /**
- * Destructor
- */
- virtual ~CmdLineInterface() {}
-
- /**
- * Adds an argument to the list of arguments to be parsed.
- * \param a - Argument to be added.
- */
- virtual void add( Arg& a )=0;
-
- /**
- * An alternative add. Functionally identical.
- * \param a - Argument to be added.
- */
- virtual void add( Arg* a )=0;
-
- /**
- * Add two Args that will be xor'd.
- * If this method is used, add does
- * not need to be called.
- * \param a - Argument to be added and xor'd.
- * \param b - Argument to be added and xor'd.
- */
- virtual void xorAdd( Arg& a, Arg& b )=0;
-
- /**
- * Add a list of Args that will be xor'd. If this method is used,
- * add does not need to be called.
- * \param xors - List of Args to be added and xor'd.
- */
- virtual void xorAdd( std::vector<Arg*>& xors )=0;
-
- /**
- * Parses the command line.
- * \param argc - Number of arguments.
- * \param argv - Array of arguments.
- */
- virtual void parse(int argc, const char * const * argv)=0;
-
- /**
- * Parses the command line.
- * \param args - A vector of strings representing the args.
- * args[0] is still the program name.
- */
- void parse(std::vector<std::string>& args);
-
- /**
- * Returns the CmdLineOutput object.
- */
- virtual CmdLineOutput* getOutput()=0;
-
- /**
- * \param co - CmdLineOutput object that we want to use instead.
- */
- virtual void setOutput(CmdLineOutput* co)=0;
-
- /**
- * Returns the version string.
- */
- virtual std::string& getVersion()=0;
-
- /**
- * Returns the program name string.
- */
- virtual std::string& getProgramName()=0;
-
- /**
- * Returns the argList.
- */
- virtual std::list<Arg*>& getArgList()=0;
-
- /**
- * Returns the XorHandler.
- */
- virtual XorHandler& getXorHandler()=0;
-
- /**
- * Returns the delimiter string.
- */
- virtual char getDelimiter()=0;
-
- /**
- * Returns the message string.
- */
- virtual std::string& getMessage()=0;
-
- /**
- * Indicates whether or not the help and version switches were created
- * automatically.
- */
- virtual bool hasHelpAndVersion()=0;
-
- /**
- * Resets the instance as if it had just been constructed so that the
- * instance can be reused.
- */
- virtual void reset()=0;
-};
-
-} //namespace
-
-
-#endif
+++ /dev/null
-
-
-/******************************************************************************
- *
- * file: CmdLineOutput.h
- *
- * Copyright (c) 2004, Michael E. Smoot
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_CMDLINEOUTPUT_H
-#define TCLAP_CMDLINEOUTPUT_H
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <iomanip>
-#include <algorithm>
-
-namespace TCLAP {
-
-class CmdLineInterface;
-class ArgException;
-
-/**
- * The interface that any output object must implement.
- */
-class CmdLineOutput
-{
-
- public:
-
- /**
- * Virtual destructor.
- */
- virtual ~CmdLineOutput() {}
-
- /**
- * Generates some sort of output for the USAGE.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void usage(CmdLineInterface& c)=0;
-
- /**
- * Generates some sort of output for the version.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void version(CmdLineInterface& c)=0;
-
- /**
- * Generates some sort of output for a failure.
- * \param c - The CmdLine object the output is generated for.
- * \param e - The ArgException that caused the failure.
- */
- virtual void failure( CmdLineInterface& c,
- ArgException& e )=0;
-
-};
-
-} //namespace TCLAP
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: Constraint.h
- *
- * Copyright (c) 2005, Michael E. Smoot
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_CONSTRAINT_H
-#define TCLAP_CONSTRAINT_H
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <iomanip>
-#include <algorithm>
-
-namespace TCLAP {
-
-/**
- * The interface that defines the interaction between the Arg and Constraint.
- */
-template<class T>
-class Constraint
-{
-
- public:
- /**
- * Returns a description of the Constraint.
- */
- virtual std::string description() const =0;
-
- /**
- * Returns the short ID for the Constraint.
- */
- virtual std::string shortID() const =0;
-
- /**
- * The method used to verify that the value parsed from the command
- * line meets the constraint.
- * \param value - The value that will be checked.
- */
- virtual bool check(const T& value) const =0;
-
- /**
- * Destructor.
- * Silences warnings about Constraint being a base class with virtual
- * functions but without a virtual destructor.
- */
- virtual ~Constraint() { ; }
-};
-
-} //namespace TCLAP
-#endif
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: DocBookOutput.h
- *
- * Copyright (c) 2004, Michael E. Smoot
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_DOCBOOKOUTPUT_H
-#define TCLAP_DOCBOOKOUTPUT_H
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <algorithm>
-
-#include <tclap/CmdLineInterface.h>
-#include <tclap/CmdLineOutput.h>
-#include <tclap/XorHandler.h>
-#include <tclap/Arg.h>
-
-namespace TCLAP {
-
-/**
- * A class that generates DocBook output for usage() method for the
- * given CmdLine and its Args.
- */
-class DocBookOutput : public CmdLineOutput
-{
-
- public:
-
- /**
- * Prints the usage to stdout. Can be overridden to
- * produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void usage(CmdLineInterface& c);
-
- /**
- * Prints the version to stdout. Can be overridden
- * to produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void version(CmdLineInterface& c);
-
- /**
- * Prints (to stderr) an error message, short usage
- * Can be overridden to produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- * \param e - The ArgException that caused the failure.
- */
- virtual void failure(CmdLineInterface& c,
- ArgException& e );
-
- DocBookOutput() : theDelimiter('=') {}
- protected:
-
- /**
- * Substitutes the char r for string x in string s.
- * \param s - The string to operate on.
- * \param r - The char to replace.
- * \param x - What to replace r with.
- */
- void substituteSpecialChars( std::string& s, char r, std::string& x );
- void removeChar( std::string& s, char r);
- void basename( std::string& s );
-
- void printShortArg(Arg* it);
- void printLongArg(Arg* it);
-
- char theDelimiter;
-};
-
-
-inline void DocBookOutput::version(CmdLineInterface& _cmd)
-{
- std::cout << _cmd.getVersion() << std::endl;
-}
-
-inline void DocBookOutput::usage(CmdLineInterface& _cmd )
-{
- std::list<Arg*> argList = _cmd.getArgList();
- std::string progName = _cmd.getProgramName();
- std::string xversion = _cmd.getVersion();
- theDelimiter = _cmd.getDelimiter();
- XorHandler xorHandler = _cmd.getXorHandler();
- std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
- basename(progName);
-
- std::cout << "<?xml version='1.0'?>" << std::endl;
- std::cout << "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.2//EN\"" << std::endl;
- std::cout << "\t\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\">" << std::endl << std::endl;
-
- std::cout << "<refentry>" << std::endl;
-
- std::cout << "<refmeta>" << std::endl;
- std::cout << "<refentrytitle>" << progName << "</refentrytitle>" << std::endl;
- std::cout << "<manvolnum>1</manvolnum>" << std::endl;
- std::cout << "</refmeta>" << std::endl;
-
- std::cout << "<refnamediv>" << std::endl;
- std::cout << "<refname>" << progName << "</refname>" << std::endl;
- std::cout << "<refpurpose>" << _cmd.getMessage() << "</refpurpose>" << std::endl;
- std::cout << "</refnamediv>" << std::endl;
-
- std::cout << "<refsynopsisdiv>" << std::endl;
- std::cout << "<cmdsynopsis>" << std::endl;
-
- std::cout << "<command>" << progName << "</command>" << std::endl;
-
- // xor
- for ( int i = 0; (unsigned int)i < xorList.size(); i++ )
- {
- std::cout << "<group choice='req'>" << std::endl;
- for ( ArgVectorIterator it = xorList[i].begin();
- it != xorList[i].end(); it++ )
- printShortArg((*it));
-
- std::cout << "</group>" << std::endl;
- }
-
- // rest of args
- for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
- if ( !xorHandler.contains( (*it) ) )
- printShortArg((*it));
-
- std::cout << "</cmdsynopsis>" << std::endl;
- std::cout << "</refsynopsisdiv>" << std::endl;
-
- std::cout << "<refsect1>" << std::endl;
- std::cout << "<title>Description</title>" << std::endl;
- std::cout << "<para>" << std::endl;
- std::cout << _cmd.getMessage() << std::endl;
- std::cout << "</para>" << std::endl;
- std::cout << "</refsect1>" << std::endl;
-
- std::cout << "<refsect1>" << std::endl;
- std::cout << "<title>Options</title>" << std::endl;
-
- std::cout << "<variablelist>" << std::endl;
-
- for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
- printLongArg((*it));
-
- std::cout << "</variablelist>" << std::endl;
- std::cout << "</refsect1>" << std::endl;
-
- std::cout << "<refsect1>" << std::endl;
- std::cout << "<title>Version</title>" << std::endl;
- std::cout << "<para>" << std::endl;
- std::cout << xversion << std::endl;
- std::cout << "</para>" << std::endl;
- std::cout << "</refsect1>" << std::endl;
-
- std::cout << "</refentry>" << std::endl;
-
-}
-
-inline void DocBookOutput::failure( CmdLineInterface& _cmd,
- ArgException& e )
-{
- static_cast<void>(_cmd); // unused
- std::cout << e.what() << std::endl;
- throw ExitException(1);
-}
-
-inline void DocBookOutput::substituteSpecialChars( std::string& s,
- char r,
- std::string& x )
-{
- size_t p;
- while ( (p = s.find_first_of(r)) != std::string::npos )
- {
- s.erase(p,1);
- s.insert(p,x);
- }
-}
-
-inline void DocBookOutput::removeChar( std::string& s, char r)
-{
- size_t p;
- while ( (p = s.find_first_of(r)) != std::string::npos )
- {
- s.erase(p,1);
- }
-}
-
-inline void DocBookOutput::basename( std::string& s )
-{
- size_t p = s.find_last_of('/');
- if ( p != std::string::npos )
- {
- s.erase(0, p + 1);
- }
-}
-
-inline void DocBookOutput::printShortArg(Arg* a)
-{
- std::string lt = "<";
- std::string gt = ">";
-
- std::string id = a->shortID();
- substituteSpecialChars(id,'<',lt);
- substituteSpecialChars(id,'>',gt);
- removeChar(id,'[');
- removeChar(id,']');
-
- std::string choice = "opt";
- if ( a->isRequired() )
- choice = "plain";
-
- std::cout << "<arg choice='" << choice << '\'';
- if ( a->acceptsMultipleValues() )
- std::cout << " rep='repeat'";
-
-
- std::cout << '>';
- if ( !a->getFlag().empty() )
- std::cout << a->flagStartChar() << a->getFlag();
- else
- std::cout << a->nameStartString() << a->getName();
- if ( a->isValueRequired() )
- {
- std::string arg = a->shortID();
- removeChar(arg,'[');
- removeChar(arg,']');
- removeChar(arg,'<');
- removeChar(arg,'>');
- arg.erase(0, arg.find_last_of(theDelimiter) + 1);
- std::cout << theDelimiter;
- std::cout << "<replaceable>" << arg << "</replaceable>";
- }
- std::cout << "</arg>" << std::endl;
-
-}
-
-inline void DocBookOutput::printLongArg(Arg* a)
-{
- std::string lt = "<";
- std::string gt = ">";
-
- std::string desc = a->getDescription();
- substituteSpecialChars(desc,'<',lt);
- substituteSpecialChars(desc,'>',gt);
-
- std::cout << "<varlistentry>" << std::endl;
-
- if ( !a->getFlag().empty() )
- {
- std::cout << "<term>" << std::endl;
- std::cout << "<option>";
- std::cout << a->flagStartChar() << a->getFlag();
- std::cout << "</option>" << std::endl;
- std::cout << "</term>" << std::endl;
- }
-
- std::cout << "<term>" << std::endl;
- std::cout << "<option>";
- std::cout << a->nameStartString() << a->getName();
- if ( a->isValueRequired() )
- {
- std::string arg = a->shortID();
- removeChar(arg,'[');
- removeChar(arg,']');
- removeChar(arg,'<');
- removeChar(arg,'>');
- arg.erase(0, arg.find_last_of(theDelimiter) + 1);
- std::cout << theDelimiter;
- std::cout << "<replaceable>" << arg << "</replaceable>";
- }
- std::cout << "</option>" << std::endl;
- std::cout << "</term>" << std::endl;
-
- std::cout << "<listitem>" << std::endl;
- std::cout << "<para>" << std::endl;
- std::cout << desc << std::endl;
- std::cout << "</para>" << std::endl;
- std::cout << "</listitem>" << std::endl;
-
- std::cout << "</varlistentry>" << std::endl;
-}
-
-} //namespace TCLAP
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: HelpVisitor.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_HELP_VISITOR_H
-#define TCLAP_HELP_VISITOR_H
-
-#include <tclap/CmdLineInterface.h>
-#include <tclap/CmdLineOutput.h>
-#include <tclap/Visitor.h>
-
-namespace TCLAP {
-
-/**
- * A Visitor object that calls the usage method of the given CmdLineOutput
- * object for the specified CmdLine object.
- */
-class HelpVisitor: public Visitor
-{
- private:
- /**
- * Prevent accidental copying.
- */
- HelpVisitor(const HelpVisitor& rhs);
- HelpVisitor& operator=(const HelpVisitor& rhs);
-
- protected:
-
- /**
- * The CmdLine the output will be generated for.
- */
- CmdLineInterface* _cmd;
-
- /**
- * The output object.
- */
- CmdLineOutput** _out;
-
- public:
-
- /**
- * Constructor.
- * \param cmd - The CmdLine the output will be generated for.
- * \param out - The type of output.
- */
- HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out)
- : Visitor(), _cmd( cmd ), _out( out ) { }
-
- /**
- * Calls the usage method of the CmdLineOutput for the
- * specified CmdLine.
- */
- void visit() { (*_out)->usage(*_cmd); throw ExitException(0); }
-
-};
-
-}
-
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: IgnoreRestVisitor.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_IGNORE_REST_VISITOR_H
-#define TCLAP_IGNORE_REST_VISITOR_H
-
-#include <tclap/Visitor.h>
-#include <tclap/Arg.h>
-
-namespace TCLAP {
-
-/**
- * A Visitor that tells the CmdLine to begin ignoring arguments after
- * this one is parsed.
- */
-class IgnoreRestVisitor: public Visitor
-{
- public:
-
- /**
- * Constructor.
- */
- IgnoreRestVisitor() : Visitor() {}
-
- /**
- * Sets Arg::_ignoreRest.
- */
- void visit() { Arg::beginIgnoring(); }
-};
-
-}
-
-#endif
+++ /dev/null
-/******************************************************************************
- *
- * file: MultiArg.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_MULTIPLE_ARGUMENT_H
-#define TCLAP_MULTIPLE_ARGUMENT_H
-
-#include <string>
-#include <vector>
-
-#include <tclap/Arg.h>
-#include <tclap/Constraint.h>
-
-namespace TCLAP {
-/**
- * An argument that allows multiple values of type T to be specified. Very
- * similar to a ValueArg, except a vector of values will be returned
- * instead of just one.
- */
-template<class T>
-class MultiArg : public Arg
-{
-public:
- typedef std::vector<T> container_type;
- typedef typename container_type::iterator iterator;
- typedef typename container_type::const_iterator const_iterator;
-
-protected:
-
- /**
- * The list of values parsed from the CmdLine.
- */
- std::vector<T> _values;
-
- /**
- * The description of type T to be used in the usage.
- */
- std::string _typeDesc;
-
- /**
- * A list of constraint on this Arg.
- */
- Constraint<T>* _constraint;
-
- /**
- * Extracts the value from the string.
- * Attempts to parse string as type T, if this fails an exception
- * is thrown.
- * \param val - The string to be read.
- */
- void _extractValue( const std::string& val );
-
- /**
- * Used by XorHandler to decide whether to keep parsing for this arg.
- */
- bool _allowMore;
-
-public:
-
- /**
- * Constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- MultiArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- Visitor* v = NULL);
-
- /**
- * Constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- MultiArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- Visitor* v = NULL );
-
- /**
- * Constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- MultiArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- Visitor* v = NULL );
-
- /**
- * Constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- MultiArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- Visitor* v = NULL );
-
- /**
- * Handles the processing of the argument.
- * This re-implements the Arg version of this method to set the
- * _value of the argument appropriately. It knows the difference
- * between labeled and unlabeled.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings. Passed from main().
- */
- virtual bool processArg(int* i, std::vector<std::string>& args);
-
- /**
- * Returns a vector of type T containing the values parsed from
- * the command line.
- */
- const std::vector<T>& getValue();
-
- /**
- * Returns an iterator over the values parsed from the command
- * line.
- */
- const_iterator begin() const { return _values.begin(); }
-
- /**
- * Returns the end of the values parsed from the command
- * line.
- */
- const_iterator end() const { return _values.end(); }
-
- /**
- * Returns the a short id string. Used in the usage.
- * \param val - value to be used.
- */
- virtual std::string shortID(const std::string& val="val") const;
-
- /**
- * Returns the a long id string. Used in the usage.
- * \param val - value to be used.
- */
- virtual std::string longID(const std::string& val="val") const;
-
- /**
- * Once we've matched the first value, then the arg is no longer
- * required.
- */
- virtual bool isRequired() const;
-
- virtual bool allowMore();
-
- virtual void reset();
-
-private:
- /**
- * Prevent accidental copying
- */
- MultiArg<T>(const MultiArg<T>& rhs);
- MultiArg<T>& operator=(const MultiArg<T>& rhs);
-
-};
-
-template<class T>
-MultiArg<T>::MultiArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- Visitor* v) :
- Arg( flag, name, desc, req, true, v ),
- _values(std::vector<T>()),
- _typeDesc( typeDesc ),
- _constraint( NULL ),
- _allowMore(false)
-{
- _acceptsMultipleValues = true;
-}
-
-template<class T>
-MultiArg<T>::MultiArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- Visitor* v)
-: Arg( flag, name, desc, req, true, v ),
- _values(std::vector<T>()),
- _typeDesc( typeDesc ),
- _constraint( NULL ),
- _allowMore(false)
-{
- parser.add( this );
- _acceptsMultipleValues = true;
-}
-
-/**
- *
- */
-template<class T>
-MultiArg<T>::MultiArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- Visitor* v)
-: Arg( flag, name, desc, req, true, v ),
- _values(std::vector<T>()),
- _typeDesc( constraint->shortID() ),
- _constraint( constraint ),
- _allowMore(false)
-{
- _acceptsMultipleValues = true;
-}
-
-template<class T>
-MultiArg<T>::MultiArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- Visitor* v)
-: Arg( flag, name, desc, req, true, v ),
- _values(std::vector<T>()),
- _typeDesc( constraint->shortID() ),
- _constraint( constraint ),
- _allowMore(false)
-{
- parser.add( this );
- _acceptsMultipleValues = true;
-}
-
-template<class T>
-const std::vector<T>& MultiArg<T>::getValue() { return _values; }
-
-template<class T>
-bool MultiArg<T>::processArg(int *i, std::vector<std::string>& args)
-{
- if ( _ignoreable && Arg::ignoreRest() )
- return false;
-
- if ( _hasBlanks( args[*i] ) )
- return false;
-
- std::string flag = args[*i];
- std::string value = "";
-
- trimFlag( flag, value );
-
- if ( argMatches( flag ) )
- {
- if ( Arg::delimiter() != ' ' && value == "" )
- throw( ArgParseException(
- "Couldn't find delimiter for this argument!",
- toString() ) );
-
- // always take the first one, regardless of start string
- if ( value == "" )
- {
- (*i)++;
- if ( static_cast<unsigned int>(*i) < args.size() )
- _extractValue( args[*i] );
- else
- throw( ArgParseException("Missing a value for this argument!",
- toString() ) );
- }
- else
- _extractValue( value );
-
- /*
- // continuing taking the args until we hit one with a start string
- while ( (unsigned int)(*i)+1 < args.size() &&
- args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
- args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
- _extractValue( args[++(*i)] );
- */
-
- _alreadySet = true;
- _checkWithVisitor();
-
- return true;
- }
- else
- return false;
-}
-
-/**
- *
- */
-template<class T>
-std::string MultiArg<T>::shortID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return Arg::shortID(_typeDesc) + " ... ";
-}
-
-/**
- *
- */
-template<class T>
-std::string MultiArg<T>::longID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return Arg::longID(_typeDesc) + " (accepted multiple times)";
-}
-
-/**
- * Once we've matched the first value, then the arg is no longer
- * required.
- */
-template<class T>
-bool MultiArg<T>::isRequired() const
-{
- if ( _required )
- {
- if ( _values.size() > 1 )
- return false;
- else
- return true;
- }
- else
- return false;
-
-}
-
-template<class T>
-void MultiArg<T>::_extractValue( const std::string& val )
-{
- try {
- T tmp;
- ExtractValue(tmp, val, typename ArgTraits<T>::ValueCategory());
- _values.push_back(tmp);
- } catch( ArgParseException &e) {
- throw ArgParseException(e.error(), toString());
- }
-
- if ( _constraint != NULL )
- if ( ! _constraint->check( _values.back() ) )
- throw( CmdLineParseException( "Value '" + val +
- "' does not meet constraint: " +
- _constraint->description(),
- toString() ) );
-}
-
-template<class T>
-bool MultiArg<T>::allowMore()
-{
- bool am = _allowMore;
- _allowMore = true;
- return am;
-}
-
-template<class T>
-void MultiArg<T>::reset()
-{
- Arg::reset();
- _values.clear();
-}
-
-} // namespace TCLAP
-
-#endif
+++ /dev/null
-
-/******************************************************************************
-*
-* file: MultiSwitchArg.h
-*
-* Copyright (c) 2003, Michael E. Smoot .
-* Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
-* Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek.
-* All rights reserved.
-*
-* See the file COPYING in the top directory of this distribution for
-* more information.
-*
-* THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-* DEALINGS IN THE SOFTWARE.
-*
-*****************************************************************************/
-
-
-#ifndef TCLAP_MULTI_SWITCH_ARG_H
-#define TCLAP_MULTI_SWITCH_ARG_H
-
-#include <string>
-#include <vector>
-
-#include <tclap/SwitchArg.h>
-
-namespace TCLAP {
-
-/**
-* A multiple switch argument. If the switch is set on the command line, then
-* the getValue method will return the number of times the switch appears.
-*/
-class MultiSwitchArg : public SwitchArg
-{
- protected:
-
- /**
- * The value of the switch.
- */
- int _value;
-
- /**
- * Used to support the reset() method so that ValueArg can be
- * reset to their constructed value.
- */
- int _default;
-
- public:
-
- /**
- * MultiSwitchArg constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param init - Optional. The initial/default value of this Arg.
- * Defaults to 0.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- MultiSwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- int init = 0,
- Visitor* v = NULL);
-
-
- /**
- * MultiSwitchArg constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param init - Optional. The initial/default value of this Arg.
- * Defaults to 0.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- MultiSwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- CmdLineInterface& parser,
- int init = 0,
- Visitor* v = NULL);
-
-
- /**
- * Handles the processing of the argument.
- * This re-implements the SwitchArg version of this method to set the
- * _value of the argument appropriately.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings. Passed
- * in from main().
- */
- virtual bool processArg(int* i, std::vector<std::string>& args);
-
- /**
- * Returns int, the number of times the switch has been set.
- */
- int getValue();
-
- /**
- * Returns the shortID for this Arg.
- */
- std::string shortID(const std::string& val) const;
-
- /**
- * Returns the longID for this Arg.
- */
- std::string longID(const std::string& val) const;
-
- void reset();
-
-};
-
-//////////////////////////////////////////////////////////////////////
-//BEGIN MultiSwitchArg.cpp
-//////////////////////////////////////////////////////////////////////
-inline MultiSwitchArg::MultiSwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- int init,
- Visitor* v )
-: SwitchArg(flag, name, desc, false, v),
-_value( init ),
-_default( init )
-{ }
-
-inline MultiSwitchArg::MultiSwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- CmdLineInterface& parser,
- int init,
- Visitor* v )
-: SwitchArg(flag, name, desc, false, v),
-_value( init ),
-_default( init )
-{
- parser.add( this );
-}
-
-inline int MultiSwitchArg::getValue() { return _value; }
-
-inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>& args)
-{
- if ( _ignoreable && Arg::ignoreRest() )
- return false;
-
- if ( argMatches( args[*i] ))
- {
- // so the isSet() method will work
- _alreadySet = true;
-
- // Matched argument: increment value.
- ++_value;
-
- _checkWithVisitor();
-
- return true;
- }
- else if ( combinedSwitchesMatch( args[*i] ) )
- {
- // so the isSet() method will work
- _alreadySet = true;
-
- // Matched argument: increment value.
- ++_value;
-
- // Check for more in argument and increment value.
- while ( combinedSwitchesMatch( args[*i] ) )
- ++_value;
-
- _checkWithVisitor();
-
- return false;
- }
- else
- return false;
-}
-
-inline std::string
-MultiSwitchArg::shortID(const std::string& val) const
-{
- return Arg::shortID(val) + " ... ";
-}
-
-inline std::string
-MultiSwitchArg::longID(const std::string& val) const
-{
- return Arg::longID(val) + " (accepted multiple times)";
-}
-
-inline void
-MultiSwitchArg::reset()
-{
- MultiSwitchArg::_value = MultiSwitchArg::_default;
-}
-
-//////////////////////////////////////////////////////////////////////
-//END MultiSwitchArg.cpp
-//////////////////////////////////////////////////////////////////////
-
-} //namespace TCLAP
-
-#endif
+++ /dev/null
-
-
-/******************************************************************************
- *
- * file: OptionalUnlabeledTracker.h
- *
- * Copyright (c) 2005, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H
-#define TCLAP_OPTIONAL_UNLABELED_TRACKER_H
-
-#include <string>
-
-namespace TCLAP {
-
-class OptionalUnlabeledTracker
-{
-
- public:
-
- static void check( bool req, const std::string& argName );
-
- static void gotOptional() { alreadyOptionalRef() = true; }
-
- static bool& alreadyOptional() { return alreadyOptionalRef(); }
-
- private:
-
- static bool& alreadyOptionalRef() { static bool ct = false; return ct; }
-};
-
-
-inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName )
-{
- if ( OptionalUnlabeledTracker::alreadyOptional() )
- throw( SpecificationException(
- "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg",
- argName ) );
-
- if ( !req )
- OptionalUnlabeledTracker::gotOptional();
-}
-
-
-} // namespace TCLAP
-
-#endif
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: StandardTraits.h
- *
- * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-// This is an internal tclap file, you should probably not have to
-// include this directly
-
-#ifndef TCLAP_STANDARD_TRAITS_H
-#define TCLAP_STANDARD_TRAITS_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h> // To check for long long
-#endif
-
-// If Microsoft has already typedef'd wchar_t as an unsigned
-// short, then compiles will break because it's as if we're
-// creating ArgTraits twice for unsigned short. Thus...
-#ifdef _MSC_VER
-#ifndef _NATIVE_WCHAR_T_DEFINED
-#define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS
-#endif
-#endif
-
-namespace TCLAP {
-
-// ======================================================================
-// Integer types
-// ======================================================================
-
-/**
- * longs have value-like semantics.
- */
-template<>
-struct ArgTraits<long> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * ints have value-like semantics.
- */
-template<>
-struct ArgTraits<int> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * shorts have value-like semantics.
- */
-template<>
-struct ArgTraits<short> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * chars have value-like semantics.
- */
-template<>
-struct ArgTraits<char> {
- typedef ValueLike ValueCategory;
-};
-
-#ifdef HAVE_LONG_LONG
-/**
- * long longs have value-like semantics.
- */
-template<>
-struct ArgTraits<long long> {
- typedef ValueLike ValueCategory;
-};
-#endif
-
-// ======================================================================
-// Unsigned integer types
-// ======================================================================
-
-/**
- * unsigned longs have value-like semantics.
- */
-template<>
-struct ArgTraits<unsigned long> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * unsigned ints have value-like semantics.
- */
-template<>
-struct ArgTraits<unsigned int> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * unsigned shorts have value-like semantics.
- */
-template<>
-struct ArgTraits<unsigned short> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * unsigned chars have value-like semantics.
- */
-template<>
-struct ArgTraits<unsigned char> {
- typedef ValueLike ValueCategory;
-};
-
-// Microsoft implements size_t awkwardly.
-#if defined(_MSC_VER) && defined(_M_X64)
-/**
- * size_ts have value-like semantics.
- */
-template<>
-struct ArgTraits<size_t> {
- typedef ValueLike ValueCategory;
-};
-#endif
-
-
-#ifdef HAVE_LONG_LONG
-/**
- * unsigned long longs have value-like semantics.
- */
-template<>
-struct ArgTraits<unsigned long long> {
- typedef ValueLike ValueCategory;
-};
-#endif
-
-// ======================================================================
-// Float types
-// ======================================================================
-
-/**
- * floats have value-like semantics.
- */
-template<>
-struct ArgTraits<float> {
- typedef ValueLike ValueCategory;
-};
-
-/**
- * doubles have value-like semantics.
- */
-template<>
-struct ArgTraits<double> {
- typedef ValueLike ValueCategory;
-};
-
-// ======================================================================
-// Other types
-// ======================================================================
-
-/**
- * bools have value-like semantics.
- */
-template<>
-struct ArgTraits<bool> {
- typedef ValueLike ValueCategory;
-};
-
-
-/**
- * wchar_ts have value-like semantics.
- */
-#ifndef TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS
-template<>
-struct ArgTraits<wchar_t> {
- typedef ValueLike ValueCategory;
-};
-#endif
-
-/**
- * Strings have string like argument traits.
- */
-template<>
-struct ArgTraits<std::string> {
- typedef StringLike ValueCategory;
-};
-
-template<typename T>
-void SetString(T &dst, const std::string &src)
-{
- dst = src;
-}
-
-} // namespace
-
-#endif
-
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: StdOutput.h
- *
- * Copyright (c) 2004, Michael E. Smoot
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_STDCMDLINEOUTPUT_H
-#define TCLAP_STDCMDLINEOUTPUT_H
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <algorithm>
-
-#include <tclap/CmdLineInterface.h>
-#include <tclap/CmdLineOutput.h>
-#include <tclap/XorHandler.h>
-#include <tclap/Arg.h>
-
-namespace TCLAP {
-
-/**
- * A class that isolates any output from the CmdLine object so that it
- * may be easily modified.
- */
-class StdOutput : public CmdLineOutput
-{
-
- public:
-
- /**
- * Prints the usage to stdout. Can be overridden to
- * produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void usage(CmdLineInterface& c);
-
- /**
- * Prints the version to stdout. Can be overridden
- * to produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void version(CmdLineInterface& c);
-
- /**
- * Prints (to stderr) an error message, short usage
- * Can be overridden to produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- * \param e - The ArgException that caused the failure.
- */
- virtual void failure(CmdLineInterface& c,
- ArgException& e );
-
- protected:
-
- /**
- * Writes a brief usage message with short args.
- * \param c - The CmdLine object the output is generated for.
- * \param os - The stream to write the message to.
- */
- void _shortUsage( CmdLineInterface& c, std::ostream& os ) const;
-
- /**
- * Writes a longer usage message with long and short args,
- * provides descriptions and prints message.
- * \param c - The CmdLine object the output is generated for.
- * \param os - The stream to write the message to.
- */
- void _longUsage( CmdLineInterface& c, std::ostream& os ) const;
-
- /**
- * This function inserts line breaks and indents long strings
- * according the params input. It will only break lines at spaces,
- * commas and pipes.
- * \param os - The stream to be printed to.
- * \param s - The string to be printed.
- * \param maxWidth - The maxWidth allowed for the output line.
- * \param indentSpaces - The number of spaces to indent the first line.
- * \param secondLineOffset - The number of spaces to indent the second
- * and all subsequent lines in addition to indentSpaces.
- */
- void spacePrint( std::ostream& os,
- const std::string& s,
- int maxWidth,
- int indentSpaces,
- int secondLineOffset ) const;
-
-};
-
-
-inline void StdOutput::version(CmdLineInterface& _cmd)
-{
- std::string progName = _cmd.getProgramName();
- std::string xversion = _cmd.getVersion();
-
- std::cout << std::endl << progName << " version: "
- << xversion << std::endl << std::endl;
-}
-
-inline void StdOutput::usage(CmdLineInterface& _cmd )
-{
- std::cout << std::endl << "USAGE: " << std::endl << std::endl;
-
- _shortUsage( _cmd, std::cout );
-
- std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
-
- _longUsage( _cmd, std::cout );
-
- std::cout << std::endl;
-
-}
-
-inline void StdOutput::failure( CmdLineInterface& _cmd,
- ArgException& e )
-{
- std::string progName = _cmd.getProgramName();
-
- std::cerr << "PARSE ERROR: " << e.argId() << std::endl
- << " " << e.error() << std::endl << std::endl;
-
- if ( _cmd.hasHelpAndVersion() )
- {
- std::cerr << "Brief USAGE: " << std::endl;
-
- _shortUsage( _cmd, std::cerr );
-
- std::cerr << std::endl << "For complete USAGE and HELP type: "
- << std::endl << " " << progName << " "
- << Arg::nameStartString() << "help"
- << std::endl << std::endl;
- }
- else
- usage(_cmd);
-
- throw ExitException(1);
-}
-
-inline void
-StdOutput::_shortUsage( CmdLineInterface& _cmd,
- std::ostream& os ) const
-{
- std::list<Arg*> argList = _cmd.getArgList();
- std::string progName = _cmd.getProgramName();
- XorHandler xorHandler = _cmd.getXorHandler();
- std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
-
- std::string s = progName + " ";
-
- // first the xor
- for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
- {
- s += " {";
- for ( ArgVectorIterator it = xorList[i].begin();
- it != xorList[i].end(); it++ )
- s += (*it)->shortID() + "|";
-
- s[s.length()-1] = '}';
- }
-
- // then the rest
- for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
- if ( !xorHandler.contains( (*it) ) )
- s += " " + (*it)->shortID();
-
- // if the program name is too long, then adjust the second line offset
- int secondLineOffset = static_cast<int>(progName.length()) + 2;
- if ( secondLineOffset > 75/2 )
- secondLineOffset = static_cast<int>(75/2);
-
- spacePrint( os, s, 75, 3, secondLineOffset );
-}
-
-inline void
-StdOutput::_longUsage( CmdLineInterface& _cmd,
- std::ostream& os ) const
-{
- std::list<Arg*> argList = _cmd.getArgList();
- std::string message = _cmd.getMessage();
- XorHandler xorHandler = _cmd.getXorHandler();
- std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
-
- // first the xor
- for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
- {
- for ( ArgVectorIterator it = xorList[i].begin();
- it != xorList[i].end();
- it++ )
- {
- spacePrint( os, (*it)->longID(), 75, 3, 3 );
- spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
-
- if ( it+1 != xorList[i].end() )
- spacePrint(os, "-- OR --", 75, 9, 0);
- }
- os << std::endl << std::endl;
- }
-
- // then the rest
- for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
- if ( !xorHandler.contains( (*it) ) )
- {
- spacePrint( os, (*it)->longID(), 75, 3, 3 );
- spacePrint( os, (*it)->getDescription(), 75, 5, 0 );
- os << std::endl;
- }
-
- os << std::endl;
-
- spacePrint( os, message, 75, 3, 0 );
-}
-
-inline void StdOutput::spacePrint( std::ostream& os,
- const std::string& s,
- int maxWidth,
- int indentSpaces,
- int secondLineOffset ) const
-{
- int len = static_cast<int>(s.length());
-
- if ( (len + indentSpaces > maxWidth) && maxWidth > 0 )
- {
- int allowedLen = maxWidth - indentSpaces;
- int start = 0;
- while ( start < len )
- {
- // find the substring length
- // int stringLen = std::min<int>( len - start, allowedLen );
- // doing it this way to support a VisualC++ 2005 bug
- using namespace std;
- int stringLen = min<int>( len - start, allowedLen );
-
- // trim the length so it doesn't end in middle of a word
- if ( stringLen == allowedLen )
- while ( stringLen >= 0 &&
- s[stringLen+start] != ' ' &&
- s[stringLen+start] != ',' &&
- s[stringLen+start] != '|' )
- stringLen--;
-
- // ok, the word is longer than the line, so just split
- // wherever the line ends
- if ( stringLen <= 0 )
- stringLen = allowedLen;
-
- // check for newlines
- for ( int i = 0; i < stringLen; i++ )
- if ( s[start+i] == '\n' )
- stringLen = i+1;
-
- // print the indent
- for ( int i = 0; i < indentSpaces; i++ )
- os << " ";
-
- if ( start == 0 )
- {
- // handle second line offsets
- indentSpaces += secondLineOffset;
-
- // adjust allowed len
- allowedLen -= secondLineOffset;
- }
-
- os << s.substr(start,stringLen) << std::endl;
-
- // so we don't start a line with a space
- while ( s[stringLen+start] == ' ' && start < len )
- start++;
-
- start += stringLen;
- }
- }
- else
- {
- for ( int i = 0; i < indentSpaces; i++ )
- os << " ";
- os << s << std::endl;
- }
-}
-
-} //namespace TCLAP
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: SwitchArg.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_SWITCH_ARG_H
-#define TCLAP_SWITCH_ARG_H
-
-#include <string>
-#include <vector>
-
-#include <tclap/Arg.h>
-
-namespace TCLAP {
-
-/**
- * A simple switch argument. If the switch is set on the command line, then
- * the getValue method will return the opposite of the default value for the
- * switch.
- */
-class SwitchArg : public Arg
-{
- protected:
-
- /**
- * The value of the switch.
- */
- bool _value;
-
- /**
- * Used to support the reset() method so that ValueArg can be
- * reset to their constructed value.
- */
- bool _default;
-
- public:
-
- /**
- * SwitchArg constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param def - The default value for this Switch.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- SwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool def = false,
- Visitor* v = NULL);
-
-
- /**
- * SwitchArg constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param def - The default value for this Switch.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- SwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- CmdLineInterface& parser,
- bool def = false,
- Visitor* v = NULL);
-
-
- /**
- * Handles the processing of the argument.
- * This re-implements the Arg version of this method to set the
- * _value of the argument appropriately.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings. Passed
- * in from main().
- */
- virtual bool processArg(int* i, std::vector<std::string>& args);
-
- /**
- * Checks a string to see if any of the chars in the string
- * match the flag for this Switch.
- */
- bool combinedSwitchesMatch(std::string& combined);
-
- /**
- * Returns bool, whether or not the switch has been set.
- */
- bool getValue();
-
- virtual void reset();
-
- private:
- /**
- * Checks to see if we've found the last match in
- * a combined string.
- */
- bool lastCombined(std::string& combined);
-
- /**
- * Does the common processing of processArg.
- */
- void commonProcessing();
-};
-
-//////////////////////////////////////////////////////////////////////
-//BEGIN SwitchArg.cpp
-//////////////////////////////////////////////////////////////////////
-inline SwitchArg::SwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool default_val,
- Visitor* v )
-: Arg(flag, name, desc, false, false, v),
- _value( default_val ),
- _default( default_val )
-{ }
-
-inline SwitchArg::SwitchArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- CmdLineInterface& parser,
- bool default_val,
- Visitor* v )
-: Arg(flag, name, desc, false, false, v),
- _value( default_val ),
- _default(default_val)
-{
- parser.add( this );
-}
-
-inline bool SwitchArg::getValue() { return _value; }
-
-inline bool SwitchArg::lastCombined(std::string& combinedSwitches )
-{
- for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
- if ( combinedSwitches[i] != Arg::blankChar() )
- return false;
-
- return true;
-}
-
-inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches )
-{
- // make sure this is actually a combined switch
- if ( combinedSwitches.length() > 0 &&
- combinedSwitches[0] != Arg::flagStartString()[0] )
- return false;
-
- // make sure it isn't a long name
- if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) ==
- Arg::nameStartString() )
- return false;
-
- // make sure the delimiter isn't in the string
- if ( combinedSwitches.find_first_of( Arg::delimiter() ) != std::string::npos )
- return false;
-
- // ok, we're not specifying a ValueArg, so we know that we have
- // a combined switch list.
- for ( unsigned int i = 1; i < combinedSwitches.length(); i++ )
- if ( _flag.length() > 0 &&
- combinedSwitches[i] == _flag[0] &&
- _flag[0] != Arg::flagStartString()[0] )
- {
- // update the combined switches so this one is no longer present
- // this is necessary so that no unlabeled args are matched
- // later in the processing.
- //combinedSwitches.erase(i,1);
- combinedSwitches[i] = Arg::blankChar();
- return true;
- }
-
- // none of the switches passed in the list match.
- return false;
-}
-
-inline void SwitchArg::commonProcessing()
-{
- if ( _xorSet )
- throw(CmdLineParseException(
- "Mutually exclusive argument already set!", toString()));
-
- if ( _alreadySet )
- throw(CmdLineParseException("Argument already set!", toString()));
-
- _alreadySet = true;
-
- if ( _value == true )
- _value = false;
- else
- _value = true;
-
- _checkWithVisitor();
-}
-
-inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
-{
- if ( _ignoreable && Arg::ignoreRest() )
- return false;
-
- // if the whole string matches the flag or name string
- if ( argMatches( args[*i] ) )
- {
- commonProcessing();
-
- return true;
- }
- // if a substring matches the flag as part of a combination
- else if ( combinedSwitchesMatch( args[*i] ) )
- {
- // check again to ensure we don't misinterpret
- // this as a MultiSwitchArg
- if ( combinedSwitchesMatch( args[*i] ) )
- throw(CmdLineParseException("Argument already set!",
- toString()));
-
- commonProcessing();
-
- // We only want to return true if we've found the last combined
- // match in the string, otherwise we return true so that other
- // switches in the combination will have a chance to match.
- return lastCombined( args[*i] );
- }
- else
- return false;
-}
-
-inline void SwitchArg::reset()
-{
- Arg::reset();
- _value = _default;
-}
-//////////////////////////////////////////////////////////////////////
-//End SwitchArg.cpp
-//////////////////////////////////////////////////////////////////////
-
-} //namespace TCLAP
-
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: UnlabeledMultiArg.h
- *
- * Copyright (c) 2003, Michael E. Smoot.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H
-#define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H
-
-#include <string>
-#include <vector>
-
-#include <tclap/MultiArg.h>
-#include <tclap/OptionalUnlabeledTracker.h>
-
-namespace TCLAP {
-
-/**
- * Just like a MultiArg, except that the arguments are unlabeled. Basically,
- * this Arg will slurp up everything that hasn't been matched to another
- * Arg.
- */
-template<class T>
-class UnlabeledMultiArg : public MultiArg<T>
-{
-
- // If compiler has two stage name lookup (as gcc >= 3.4 does)
- // this is required to prevent undef. symbols
- using MultiArg<T>::_ignoreable;
- using MultiArg<T>::_hasBlanks;
- using MultiArg<T>::_extractValue;
- using MultiArg<T>::_typeDesc;
- using MultiArg<T>::_name;
- using MultiArg<T>::_description;
- using MultiArg<T>::_alreadySet;
- using MultiArg<T>::toString;
-
- public:
-
- /**
- * Constructor.
- * \param name - The name of the Arg. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param ignoreable - Whether or not this argument can be ignored
- * using the "--" flag.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- UnlabeledMultiArg( const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- bool ignoreable = false,
- Visitor* v = NULL );
- /**
- * Constructor.
- * \param name - The name of the Arg. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param ignoreable - Whether or not this argument can be ignored
- * using the "--" flag.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- UnlabeledMultiArg( const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- bool ignoreable = false,
- Visitor* v = NULL );
-
- /**
- * Constructor.
- * \param name - The name of the Arg. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param ignoreable - Whether or not this argument can be ignored
- * using the "--" flag.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- UnlabeledMultiArg( const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- bool ignoreable = false,
- Visitor* v = NULL );
-
- /**
- * Constructor.
- * \param name - The name of the Arg. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param ignoreable - Whether or not this argument can be ignored
- * using the "--" flag.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- UnlabeledMultiArg( const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- bool ignoreable = false,
- Visitor* v = NULL );
-
- /**
- * Handles the processing of the argument.
- * This re-implements the Arg version of this method to set the
- * _value of the argument appropriately. It knows the difference
- * between labeled and unlabeled.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings. Passed from main().
- */
- virtual bool processArg(int* i, std::vector<std::string>& args);
-
- /**
- * Returns the a short id string. Used in the usage.
- * \param val - value to be used.
- */
- virtual std::string shortID(const std::string& val="val") const;
-
- /**
- * Returns the a long id string. Used in the usage.
- * \param val - value to be used.
- */
- virtual std::string longID(const std::string& val="val") const;
-
- /**
- * Operator ==.
- * \param a - The Arg to be compared to this.
- */
- virtual bool operator==(const Arg& a) const;
-
- /**
- * Pushes this to back of list rather than front.
- * \param argList - The list this should be added to.
- */
- virtual void addToList( std::list<Arg*>& argList ) const;
-};
-
-template<class T>
-UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- bool ignoreable,
- Visitor* v)
-: MultiArg<T>("", name, desc, req, typeDesc, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(true, toString());
-}
-
-template<class T>
-UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
- const std::string& desc,
- bool req,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- bool ignoreable,
- Visitor* v)
-: MultiArg<T>("", name, desc, req, typeDesc, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(true, toString());
- parser.add( this );
-}
-
-
-template<class T>
-UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- bool ignoreable,
- Visitor* v)
-: MultiArg<T>("", name, desc, req, constraint, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(true, toString());
-}
-
-template<class T>
-UnlabeledMultiArg<T>::UnlabeledMultiArg(const std::string& name,
- const std::string& desc,
- bool req,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- bool ignoreable,
- Visitor* v)
-: MultiArg<T>("", name, desc, req, constraint, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(true, toString());
- parser.add( this );
-}
-
-
-template<class T>
-bool UnlabeledMultiArg<T>::processArg(int *i, std::vector<std::string>& args)
-{
-
- if ( _hasBlanks( args[*i] ) )
- return false;
-
- // never ignore an unlabeled multi arg
-
-
- // always take the first value, regardless of the start string
- _extractValue( args[(*i)] );
-
- /*
- // continue taking args until we hit the end or a start string
- while ( (unsigned int)(*i)+1 < args.size() &&
- args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 &&
- args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 )
- _extractValue( args[++(*i)] );
- */
-
- _alreadySet = true;
-
- return true;
-}
-
-template<class T>
-std::string UnlabeledMultiArg<T>::shortID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return std::string("<") + _typeDesc + "> ...";
-}
-
-template<class T>
-std::string UnlabeledMultiArg<T>::longID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return std::string("<") + _typeDesc + "> (accepted multiple times)";
-}
-
-template<class T>
-bool UnlabeledMultiArg<T>::operator==(const Arg& a) const
-{
- if ( _name == a.getName() || _description == a.getDescription() )
- return true;
- else
- return false;
-}
-
-template<class T>
-void UnlabeledMultiArg<T>::addToList( std::list<Arg*>& argList ) const
-{
- argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) );
-}
-
-}
-
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: UnlabeledValueArg.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H
-#define TCLAP_UNLABELED_VALUE_ARGUMENT_H
-
-#include <string>
-#include <vector>
-
-#include <tclap/ValueArg.h>
-#include <tclap/OptionalUnlabeledTracker.h>
-
-
-namespace TCLAP {
-
-/**
- * The basic unlabeled argument that parses a value.
- * This is a template class, which means the type T defines the type
- * that a given object will attempt to parse when an UnlabeledValueArg
- * is reached in the list of args that the CmdLine iterates over.
- */
-template<class T>
-class UnlabeledValueArg : public ValueArg<T>
-{
-
- // If compiler has two stage name lookup (as gcc >= 3.4 does)
- // this is required to prevent undef. symbols
- using ValueArg<T>::_ignoreable;
- using ValueArg<T>::_hasBlanks;
- using ValueArg<T>::_extractValue;
- using ValueArg<T>::_typeDesc;
- using ValueArg<T>::_name;
- using ValueArg<T>::_description;
- using ValueArg<T>::_alreadySet;
- using ValueArg<T>::toString;
-
- public:
-
- /**
- * UnlabeledValueArg constructor.
- * \param name - A one word name for the argument. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param ignoreable - Allows you to specify that this argument can be
- * ignored if the '--' flag is set. This defaults to false (cannot
- * be ignored) and should generally stay that way unless you have
- * some special need for certain arguments to be ignored.
- * \param v - Optional Visitor. You should leave this blank unless
- * you have a very good reason.
- */
- UnlabeledValueArg( const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- const std::string& typeDesc,
- bool ignoreable = false,
- Visitor* v = NULL);
-
- /**
- * UnlabeledValueArg constructor.
- * \param name - A one word name for the argument. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param ignoreable - Allows you to specify that this argument can be
- * ignored if the '--' flag is set. This defaults to false (cannot
- * be ignored) and should generally stay that way unless you have
- * some special need for certain arguments to be ignored.
- * \param v - Optional Visitor. You should leave this blank unless
- * you have a very good reason.
- */
- UnlabeledValueArg( const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- bool ignoreable = false,
- Visitor* v = NULL );
-
- /**
- * UnlabeledValueArg constructor.
- * \param name - A one word name for the argument. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param ignoreable - Allows you to specify that this argument can be
- * ignored if the '--' flag is set. This defaults to false (cannot
- * be ignored) and should generally stay that way unless you have
- * some special need for certain arguments to be ignored.
- * \param v - Optional Visitor. You should leave this blank unless
- * you have a very good reason.
- */
- UnlabeledValueArg( const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- Constraint<T>* constraint,
- bool ignoreable = false,
- Visitor* v = NULL );
-
-
- /**
- * UnlabeledValueArg constructor.
- * \param name - A one word name for the argument. Note that this is used for
- * identification, not as a long flag.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param ignoreable - Allows you to specify that this argument can be
- * ignored if the '--' flag is set. This defaults to false (cannot
- * be ignored) and should generally stay that way unless you have
- * some special need for certain arguments to be ignored.
- * \param v - Optional Visitor. You should leave this blank unless
- * you have a very good reason.
- */
- UnlabeledValueArg( const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- bool ignoreable = false,
- Visitor* v = NULL);
-
- /**
- * Handles the processing of the argument.
- * This re-implements the Arg version of this method to set the
- * _value of the argument appropriately. Handling specific to
- * unlabeled arguments.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings.
- */
- virtual bool processArg(int* i, std::vector<std::string>& args);
-
- /**
- * Overrides shortID for specific behavior.
- */
- virtual std::string shortID(const std::string& val="val") const;
-
- /**
- * Overrides longID for specific behavior.
- */
- virtual std::string longID(const std::string& val="val") const;
-
- /**
- * Overrides operator== for specific behavior.
- */
- virtual bool operator==(const Arg& a ) const;
-
- /**
- * Instead of pushing to the front of list, push to the back.
- * \param argList - The list to add this to.
- */
- virtual void addToList( std::list<Arg*>& argList ) const;
-
-};
-
-/**
- * Constructor implementation.
- */
-template<class T>
-UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- const std::string& typeDesc,
- bool ignoreable,
- Visitor* v)
-: ValueArg<T>("", name, desc, req, val, typeDesc, v)
-{
- _ignoreable = ignoreable;
-
- OptionalUnlabeledTracker::check(req, toString());
-
-}
-
-template<class T>
-UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- bool ignoreable,
- Visitor* v)
-: ValueArg<T>("", name, desc, req, val, typeDesc, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(req, toString());
- parser.add( this );
-}
-
-/**
- * Constructor implementation.
- */
-template<class T>
-UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- Constraint<T>* constraint,
- bool ignoreable,
- Visitor* v)
-: ValueArg<T>("", name, desc, req, val, constraint, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(req, toString());
-}
-
-template<class T>
-UnlabeledValueArg<T>::UnlabeledValueArg(const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- bool ignoreable,
- Visitor* v)
-: ValueArg<T>("", name, desc, req, val, constraint, v)
-{
- _ignoreable = ignoreable;
- OptionalUnlabeledTracker::check(req, toString());
- parser.add( this );
-}
-
-/**
- * Implementation of processArg().
- */
-template<class T>
-bool UnlabeledValueArg<T>::processArg(int *i, std::vector<std::string>& args)
-{
-
- if ( _alreadySet )
- return false;
-
- if ( _hasBlanks( args[*i] ) )
- return false;
-
- // never ignore an unlabeled arg
-
- _extractValue( args[*i] );
- _alreadySet = true;
- return true;
-}
-
-/**
- * Overriding shortID for specific output.
- */
-template<class T>
-std::string UnlabeledValueArg<T>::shortID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return std::string("<") + _typeDesc + ">";
-}
-
-/**
- * Overriding longID for specific output.
- */
-template<class T>
-std::string UnlabeledValueArg<T>::longID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
-
- // Ideally we would like to be able to use RTTI to return the name
- // of the type required for this argument. However, g++ at least,
- // doesn't appear to return terribly useful "names" of the types.
- return std::string("<") + _typeDesc + ">";
-}
-
-/**
- * Overriding operator== for specific behavior.
- */
-template<class T>
-bool UnlabeledValueArg<T>::operator==(const Arg& a ) const
-{
- if ( _name == a.getName() || _description == a.getDescription() )
- return true;
- else
- return false;
-}
-
-template<class T>
-void UnlabeledValueArg<T>::addToList( std::list<Arg*>& argList ) const
-{
- argList.push_back( const_cast<Arg*>(static_cast<const Arg* const>(this)) );
-}
-
-}
-#endif
+++ /dev/null
-/******************************************************************************
- *
- * file: ValueArg.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_VALUE_ARGUMENT_H
-#define TCLAP_VALUE_ARGUMENT_H
-
-#include <string>
-#include <vector>
-
-#include <tclap/Arg.h>
-#include <tclap/Constraint.h>
-
-namespace TCLAP {
-
-/**
- * The basic labeled argument that parses a value.
- * This is a template class, which means the type T defines the type
- * that a given object will attempt to parse when the flag/name is matched
- * on the command line. While there is nothing stopping you from creating
- * an unflagged ValueArg, it is unwise and would cause significant problems.
- * Instead use an UnlabeledValueArg.
- */
-template<class T>
-class ValueArg : public Arg
-{
- protected:
-
- /**
- * The value parsed from the command line.
- * Can be of any type, as long as the >> operator for the type
- * is defined.
- */
- T _value;
-
- /**
- * Used to support the reset() method so that ValueArg can be
- * reset to their constructed value.
- */
- T _default;
-
- /**
- * A human readable description of the type to be parsed.
- * This is a hack, plain and simple. Ideally we would use RTTI to
- * return the name of type T, but until there is some sort of
- * consistent support for human readable names, we are left to our
- * own devices.
- */
- std::string _typeDesc;
-
- /**
- * A Constraint this Arg must conform to.
- */
- Constraint<T>* _constraint;
-
- /**
- * Extracts the value from the string.
- * Attempts to parse string as type T, if this fails an exception
- * is thrown.
- * \param val - value to be parsed.
- */
- void _extractValue( const std::string& val );
-
- public:
-
- /**
- * Labeled ValueArg constructor.
- * You could conceivably call this constructor with a blank flag,
- * but that would make you a bad person. It would also cause
- * an exception to be thrown. If you want an unlabeled argument,
- * use the other constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- ValueArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- const std::string& typeDesc,
- Visitor* v = NULL);
-
-
- /**
- * Labeled ValueArg constructor.
- * You could conceivably call this constructor with a blank flag,
- * but that would make you a bad person. It would also cause
- * an exception to be thrown. If you want an unlabeled argument,
- * use the other constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param typeDesc - A short, human readable description of the
- * type that this object expects. This is used in the generation
- * of the USAGE statement. The goal is to be helpful to the end user
- * of the program.
- * \param parser - A CmdLine parser object to add this Arg to
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- ValueArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- Visitor* v = NULL );
-
- /**
- * Labeled ValueArg constructor.
- * You could conceivably call this constructor with a blank flag,
- * but that would make you a bad person. It would also cause
- * an exception to be thrown. If you want an unlabeled argument,
- * use the other constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param parser - A CmdLine parser object to add this Arg to.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- ValueArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- Visitor* v = NULL );
-
- /**
- * Labeled ValueArg constructor.
- * You could conceivably call this constructor with a blank flag,
- * but that would make you a bad person. It would also cause
- * an exception to be thrown. If you want an unlabeled argument,
- * use the other constructor.
- * \param flag - The one character flag that identifies this
- * argument on the command line.
- * \param name - A one word name for the argument. Can be
- * used as a long flag on the command line.
- * \param desc - A description of what the argument is for or
- * does.
- * \param req - Whether the argument is required on the command
- * line.
- * \param value - The default value assigned to this argument if it
- * is not present on the command line.
- * \param constraint - A pointer to a Constraint object used
- * to constrain this Arg.
- * \param v - An optional visitor. You probably should not
- * use this unless you have a very good reason.
- */
- ValueArg( const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T value,
- Constraint<T>* constraint,
- Visitor* v = NULL );
-
- /**
- * Handles the processing of the argument.
- * This re-implements the Arg version of this method to set the
- * _value of the argument appropriately. It knows the difference
- * between labeled and unlabeled.
- * \param i - Pointer the the current argument in the list.
- * \param args - Mutable list of strings. Passed
- * in from main().
- */
- virtual bool processArg(int* i, std::vector<std::string>& args);
-
- /**
- * Returns the value of the argument.
- */
- T& getValue() ;
-
- /**
- * Specialization of shortID.
- * \param val - value to be used.
- */
- virtual std::string shortID(const std::string& val = "val") const;
-
- /**
- * Specialization of longID.
- * \param val - value to be used.
- */
- virtual std::string longID(const std::string& val = "val") const;
-
- virtual void reset() ;
-
-private:
- /**
- * Prevent accidental copying
- */
- ValueArg<T>(const ValueArg<T>& rhs);
- ValueArg<T>& operator=(const ValueArg<T>& rhs);
-};
-
-
-/**
- * Constructor implementation.
- */
-template<class T>
-ValueArg<T>::ValueArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- const std::string& typeDesc,
- Visitor* v)
-: Arg(flag, name, desc, req, true, v),
- _value( val ),
- _default( val ),
- _typeDesc( typeDesc ),
- _constraint( NULL )
-{ }
-
-template<class T>
-ValueArg<T>::ValueArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- const std::string& typeDesc,
- CmdLineInterface& parser,
- Visitor* v)
-: Arg(flag, name, desc, req, true, v),
- _value( val ),
- _default( val ),
- _typeDesc( typeDesc ),
- _constraint( NULL )
-{
- parser.add( this );
-}
-
-template<class T>
-ValueArg<T>::ValueArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- Constraint<T>* constraint,
- Visitor* v)
-: Arg(flag, name, desc, req, true, v),
- _value( val ),
- _default( val ),
- _typeDesc( constraint->shortID() ),
- _constraint( constraint )
-{ }
-
-template<class T>
-ValueArg<T>::ValueArg(const std::string& flag,
- const std::string& name,
- const std::string& desc,
- bool req,
- T val,
- Constraint<T>* constraint,
- CmdLineInterface& parser,
- Visitor* v)
-: Arg(flag, name, desc, req, true, v),
- _value( val ),
- _default( val ),
- _typeDesc( constraint->shortID() ),
- _constraint( constraint )
-{
- parser.add( this );
-}
-
-
-/**
- * Implementation of getValue().
- */
-template<class T>
-T& ValueArg<T>::getValue() { return _value; }
-
-/**
- * Implementation of processArg().
- */
-template<class T>
-bool ValueArg<T>::processArg(int *i, std::vector<std::string>& args)
-{
- if ( _ignoreable && Arg::ignoreRest() )
- return false;
-
- if ( _hasBlanks( args[*i] ) )
- return false;
-
- std::string flag = args[*i];
-
- std::string value = "";
- trimFlag( flag, value );
-
- if ( argMatches( flag ) )
- {
- if ( _alreadySet )
- {
- if ( _xorSet )
- throw( CmdLineParseException(
- "Mutually exclusive argument already set!",
- toString()) );
- else
- throw( CmdLineParseException("Argument already set!",
- toString()) );
- }
-
- if ( Arg::delimiter() != ' ' && value == "" )
- throw( ArgParseException(
- "Couldn't find delimiter for this argument!",
- toString() ) );
-
- if ( value == "" )
- {
- (*i)++;
- if ( static_cast<unsigned int>(*i) < args.size() )
- _extractValue( args[*i] );
- else
- throw( ArgParseException("Missing a value for this argument!",
- toString() ) );
- }
- else
- _extractValue( value );
-
- _alreadySet = true;
- _checkWithVisitor();
- return true;
- }
- else
- return false;
-}
-
-/**
- * Implementation of shortID.
- */
-template<class T>
-std::string ValueArg<T>::shortID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return Arg::shortID( _typeDesc );
-}
-
-/**
- * Implementation of longID.
- */
-template<class T>
-std::string ValueArg<T>::longID(const std::string& val) const
-{
- static_cast<void>(val); // Ignore input, don't warn
- return Arg::longID( _typeDesc );
-}
-
-template<class T>
-void ValueArg<T>::_extractValue( const std::string& val )
-{
- try {
- ExtractValue(_value, val, typename ArgTraits<T>::ValueCategory());
- } catch( ArgParseException &e) {
- throw ArgParseException(e.error(), toString());
- }
-
- if ( _constraint != NULL )
- if ( ! _constraint->check( _value ) )
- throw( CmdLineParseException( "Value '" + val +
- + "' does not meet constraint: "
- + _constraint->description(),
- toString() ) );
-}
-
-template<class T>
-void ValueArg<T>::reset()
-{
- Arg::reset();
- _value = _default;
-}
-
-} // namespace TCLAP
-
-#endif
+++ /dev/null
-
-
-/******************************************************************************
- *
- * file: ValuesConstraint.h
- *
- * Copyright (c) 2005, Michael E. Smoot
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_VALUESCONSTRAINT_H
-#define TCLAP_VALUESCONSTRAINT_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string>
-#include <vector>
-#include <tclap/Constraint.h>
-#include <tclap/sstream.h>
-
-namespace TCLAP {
-
-/**
- * A Constraint that constrains the Arg to only those values specified
- * in the constraint.
- */
-template<class T>
-class ValuesConstraint : public Constraint<T>
-{
-
- public:
-
- /**
- * Constructor.
- * \param allowed - vector of allowed values.
- */
- ValuesConstraint(std::vector<T>& allowed);
-
- /**
- * Virtual destructor.
- */
- virtual ~ValuesConstraint() {}
-
- /**
- * Returns a description of the Constraint.
- */
- virtual std::string description() const;
-
- /**
- * Returns the short ID for the Constraint.
- */
- virtual std::string shortID() const;
-
- /**
- * The method used to verify that the value parsed from the command
- * line meets the constraint.
- * \param value - The value that will be checked.
- */
- virtual bool check(const T& value) const;
-
- protected:
-
- /**
- * The list of valid values.
- */
- std::vector<T> _allowed;
-
- /**
- * The string used to describe the allowed values of this constraint.
- */
- std::string _typeDesc;
-
-};
-
-template<class T>
-ValuesConstraint<T>::ValuesConstraint(std::vector<T>& allowed)
-: _allowed(allowed),
- _typeDesc("")
-{
- for ( unsigned int i = 0; i < _allowed.size(); i++ )
- {
-
-#if defined(HAVE_SSTREAM)
- std::ostringstream os;
-#elif defined(HAVE_STRSTREAM)
- std::ostrstream os;
-#else
-#error "Need a stringstream (sstream or strstream) to compile!"
-#endif
-
- os << _allowed[i];
-
- std::string temp( os.str() );
-
- if ( i > 0 )
- _typeDesc += "|";
- _typeDesc += temp;
- }
-}
-
-template<class T>
-bool ValuesConstraint<T>::check( const T& val ) const
-{
- if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() )
- return false;
- else
- return true;
-}
-
-template<class T>
-std::string ValuesConstraint<T>::shortID() const
-{
- return _typeDesc;
-}
-
-template<class T>
-std::string ValuesConstraint<T>::description() const
-{
- return _typeDesc;
-}
-
-
-} //namespace TCLAP
-#endif
-
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: VersionVisitor.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_VERSION_VISITOR_H
-#define TCLAP_VERSION_VISITOR_H
-
-#include <tclap/CmdLineInterface.h>
-#include <tclap/CmdLineOutput.h>
-#include <tclap/Visitor.h>
-
-namespace TCLAP {
-
-/**
- * A Visitor that will call the version method of the given CmdLineOutput
- * for the specified CmdLine object and then exit.
- */
-class VersionVisitor: public Visitor
-{
- private:
- /**
- * Prevent accidental copying
- */
- VersionVisitor(const VersionVisitor& rhs);
- VersionVisitor& operator=(const VersionVisitor& rhs);
-
- protected:
-
- /**
- * The CmdLine of interest.
- */
- CmdLineInterface* _cmd;
-
- /**
- * The output object.
- */
- CmdLineOutput** _out;
-
- public:
-
- /**
- * Constructor.
- * \param cmd - The CmdLine the output is generated for.
- * \param out - The type of output.
- */
- VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out )
- : Visitor(), _cmd( cmd ), _out( out ) { }
-
- /**
- * Calls the version method of the output object using the
- * specified CmdLine.
- */
- void visit() {
- (*_out)->version(*_cmd);
- throw ExitException(0);
- }
-
-};
-
-}
-
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: Visitor.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-
-#ifndef TCLAP_VISITOR_H
-#define TCLAP_VISITOR_H
-
-namespace TCLAP {
-
-/**
- * A base class that defines the interface for visitors.
- */
-class Visitor
-{
- public:
-
- /**
- * Constructor. Does nothing.
- */
- Visitor() { }
-
- /**
- * Destructor. Does nothing.
- */
- virtual ~Visitor() { }
-
- /**
- * Does nothing. Should be overridden by child.
- */
- virtual void visit() { }
-};
-
-}
-
-#endif
+++ /dev/null
-
-/******************************************************************************
- *
- * file: XorHandler.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_XORHANDLER_H
-#define TCLAP_XORHANDLER_H
-
-#include <tclap/Arg.h>
-#include <string>
-#include <vector>
-#include <algorithm>
-#include <iostream>
-
-namespace TCLAP {
-
-/**
- * This class handles lists of Arg's that are to be XOR'd on the command
- * line. This is used by CmdLine and you shouldn't ever use it.
- */
-class XorHandler
-{
- protected:
-
- /**
- * The list of of lists of Arg's to be or'd together.
- */
- std::vector< std::vector<Arg*> > _orList;
-
- public:
-
- /**
- * Constructor. Does nothing.
- */
- XorHandler( ) : _orList(std::vector< std::vector<Arg*> >()) {}
-
- /**
- * Add a list of Arg*'s that will be xor'd together.
- * \param ors - list of Arg* that will be xor'd.
- */
- void add( std::vector<Arg*>& ors );
-
- /**
- * Checks whether the specified Arg is in one of the xor lists and
- * if it does match one, returns the size of the xor list that the
- * Arg matched. If the Arg matches, then it also sets the rest of
- * the Arg's in the list. You shouldn't use this.
- * \param a - The Arg to be checked.
- */
- int check( const Arg* a );
-
- /**
- * Returns the XOR specific short usage.
- */
- std::string shortUsage();
-
- /**
- * Prints the XOR specific long usage.
- * \param os - Stream to print to.
- */
- void printLongUsage(std::ostream& os);
-
- /**
- * Simply checks whether the Arg is contained in one of the arg
- * lists.
- * \param a - The Arg to be checked.
- */
- bool contains( const Arg* a );
-
- std::vector< std::vector<Arg*> >& getXorList();
-
-};
-
-
-//////////////////////////////////////////////////////////////////////
-//BEGIN XOR.cpp
-//////////////////////////////////////////////////////////////////////
-inline void XorHandler::add( std::vector<Arg*>& ors )
-{
- _orList.push_back( ors );
-}
-
-inline int XorHandler::check( const Arg* a )
-{
- // iterate over each XOR list
- for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
- {
- // if the XOR list contains the arg..
- ArgVectorIterator ait = std::find( _orList[i].begin(),
- _orList[i].end(), a );
- if ( ait != _orList[i].end() )
- {
- // first check to see if a mutually exclusive switch
- // has not already been set
- for ( ArgVectorIterator it = _orList[i].begin();
- it != _orList[i].end();
- it++ )
- if ( a != (*it) && (*it)->isSet() )
- throw(CmdLineParseException(
- "Mutually exclusive argument already set!",
- (*it)->toString()));
-
- // go through and set each arg that is not a
- for ( ArgVectorIterator it = _orList[i].begin();
- it != _orList[i].end();
- it++ )
- if ( a != (*it) )
- (*it)->xorSet();
-
- // return the number of required args that have now been set
- if ( (*ait)->allowMore() )
- return 0;
- else
- return static_cast<int>(_orList[i].size());
- }
- }
-
- if ( a->isRequired() )
- return 1;
- else
- return 0;
-}
-
-inline bool XorHandler::contains( const Arg* a )
-{
- for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
- for ( ArgVectorIterator it = _orList[i].begin();
- it != _orList[i].end();
- it++ )
- if ( a == (*it) )
- return true;
-
- return false;
-}
-
-inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
-{
- return _orList;
-}
-
-
-
-//////////////////////////////////////////////////////////////////////
-//END XOR.cpp
-//////////////////////////////////////////////////////////////////////
-
-} //namespace TCLAP
-
-#endif
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: ZshCompletionOutput.h
- *
- * Copyright (c) 2006, Oliver Kiddle
- * Copyright (c) 2017 Google Inc.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H
-#define TCLAP_ZSHCOMPLETIONOUTPUT_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string>
-#include <vector>
-#include <list>
-#include <iostream>
-#include <map>
-
-#include <tclap/CmdLineInterface.h>
-#include <tclap/CmdLineOutput.h>
-#include <tclap/XorHandler.h>
-#include <tclap/Arg.h>
-#include <tclap/sstream.h>
-
-namespace TCLAP {
-
-/**
- * A class that generates a Zsh completion function as output from the usage()
- * method for the given CmdLine and its Args.
- */
-class ZshCompletionOutput : public CmdLineOutput
-{
-
- public:
-
- ZshCompletionOutput();
-
- /**
- * Prints the usage to stdout. Can be overridden to
- * produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void usage(CmdLineInterface& c);
-
- /**
- * Prints the version to stdout. Can be overridden
- * to produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- */
- virtual void version(CmdLineInterface& c);
-
- /**
- * Prints (to stderr) an error message, short usage
- * Can be overridden to produce alternative behavior.
- * \param c - The CmdLine object the output is generated for.
- * \param e - The ArgException that caused the failure.
- */
- virtual void failure(CmdLineInterface& c,
- ArgException& e );
-
- protected:
-
- void basename( std::string& s );
- void quoteSpecialChars( std::string& s );
-
- std::string getMutexList( CmdLineInterface& _cmd, Arg* a );
- void printOption( Arg* it, std::string mutex );
- void printArg( Arg* it );
-
- std::map<std::string, std::string> common;
- char theDelimiter;
-};
-
-ZshCompletionOutput::ZshCompletionOutput()
-: common(std::map<std::string, std::string>()),
- theDelimiter('=')
-{
- common["host"] = "_hosts";
- common["hostname"] = "_hosts";
- common["file"] = "_files";
- common["filename"] = "_files";
- common["user"] = "_users";
- common["username"] = "_users";
- common["directory"] = "_directories";
- common["path"] = "_directories";
- common["url"] = "_urls";
-}
-
-inline void ZshCompletionOutput::version(CmdLineInterface& _cmd)
-{
- std::cout << _cmd.getVersion() << std::endl;
-}
-
-inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd )
-{
- std::list<Arg*> argList = _cmd.getArgList();
- std::string progName = _cmd.getProgramName();
- std::string xversion = _cmd.getVersion();
- theDelimiter = _cmd.getDelimiter();
- basename(progName);
-
- std::cout << "#compdef " << progName << std::endl << std::endl <<
- "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl <<
- "_arguments -s -S";
-
- for (ArgListIterator it = argList.begin(); it != argList.end(); it++)
- {
- if ( (*it)->shortID().at(0) == '<' )
- printArg((*it));
- else if ( (*it)->getFlag() != "-" )
- printOption((*it), getMutexList(_cmd, *it));
- }
-
- std::cout << std::endl;
-}
-
-inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd,
- ArgException& e )
-{
- static_cast<void>(_cmd); // unused
- std::cout << e.what() << std::endl;
-}
-
-inline void ZshCompletionOutput::quoteSpecialChars( std::string& s )
-{
- size_t idx = s.find_last_of(':');
- while ( idx != std::string::npos )
- {
- s.insert(idx, 1, '\\');
- idx = s.find_last_of(':', idx);
- }
- idx = s.find_last_of('\'');
- while ( idx != std::string::npos )
- {
- s.insert(idx, "'\\'");
- if (idx == 0)
- idx = std::string::npos;
- else
- idx = s.find_last_of('\'', --idx);
- }
-}
-
-inline void ZshCompletionOutput::basename( std::string& s )
-{
- size_t p = s.find_last_of('/');
- if ( p != std::string::npos )
- {
- s.erase(0, p + 1);
- }
-}
-
-inline void ZshCompletionOutput::printArg(Arg* a)
-{
- static int count = 1;
-
- std::cout << " \\" << std::endl << " '";
- if ( a->acceptsMultipleValues() )
- std::cout << '*';
- else
- std::cout << count++;
- std::cout << ':';
- if ( !a->isRequired() )
- std::cout << ':';
-
- std::cout << a->getName() << ':';
- std::map<std::string, std::string>::iterator compArg = common.find(a->getName());
- if ( compArg != common.end() )
- {
- std::cout << compArg->second;
- }
- else
- {
- std::cout << "_guard \"^-*\" " << a->getName();
- }
- std::cout << '\'';
-}
-
-inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex)
-{
- std::string flag = a->flagStartChar() + a->getFlag();
- std::string name = a->nameStartString() + a->getName();
- std::string desc = a->getDescription();
-
- // remove full stop and capitalization from description as
- // this is the convention for zsh function
- if (!desc.compare(0, 12, "(required) "))
- {
- desc.erase(0, 12);
- }
- if (!desc.compare(0, 15, "(OR required) "))
- {
- desc.erase(0, 15);
- }
- size_t len = desc.length();
- if (len && desc.at(--len) == '.')
- {
- desc.erase(len);
- }
- if (len)
- {
- desc.replace(0, 1, 1, tolower(desc.at(0)));
- }
-
- std::cout << " \\" << std::endl << " '" << mutex;
-
- if ( a->getFlag().empty() )
- {
- std::cout << name;
- }
- else
- {
- std::cout << "'{" << flag << ',' << name << "}'";
- }
- if ( theDelimiter == '=' && a->isValueRequired() )
- std::cout << "=-";
- quoteSpecialChars(desc);
- std::cout << '[' << desc << ']';
-
- if ( a->isValueRequired() )
- {
- std::string arg = a->shortID();
- // Example arg: "[-A <integer>] ... "
- size_t pos = arg.rfind(" ... ");
- if (pos != std::string::npos) {
- arg.erase(pos);
- }
-
- arg.erase(0, arg.find_last_of(theDelimiter) + 1);
- if ( arg.at(arg.length()-1) == ']' )
- arg.erase(arg.length()-1);
- if ( arg.at(arg.length()-1) == ']' )
- {
- arg.erase(arg.length()-1);
- }
- if ( arg.at(0) == '<' )
- {
- arg.erase(arg.length()-1);
- arg.erase(0, 1);
- }
- size_t p = arg.find('|');
- if ( p != std::string::npos )
- {
- do
- {
- arg.replace(p, 1, 1, ' ');
- }
- while ( (p = arg.find_first_of('|', p)) != std::string::npos );
- quoteSpecialChars(arg);
- std::cout << ": :(" << arg << ')';
- }
- else
- {
- std::cout << ':' << arg;
- std::map<std::string, std::string>::iterator compArg = common.find(arg);
- if ( compArg != common.end() )
- {
- std::cout << ':' << compArg->second;
- }
- }
- }
-
- std::cout << '\'';
-}
-
-inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a)
-{
- XorHandler xorHandler = _cmd.getXorHandler();
- std::vector< std::vector<Arg*> > xorList = xorHandler.getXorList();
-
- if (a->getName() == "help" || a->getName() == "version")
- {
- return "(-)";
- }
-
- ostringstream list;
- if ( a->acceptsMultipleValues() )
- {
- list << '*';
- }
-
- for ( int i = 0; static_cast<unsigned int>(i) < xorList.size(); i++ )
- {
- for ( ArgVectorIterator it = xorList[i].begin();
- it != xorList[i].end();
- it++)
- if ( a == (*it) )
- {
- list << '(';
- for ( ArgVectorIterator iu = xorList[i].begin();
- iu != xorList[i].end();
- iu++ )
- {
- bool notCur = (*iu) != a;
- bool hasFlag = !(*iu)->getFlag().empty();
- if ( iu != xorList[i].begin() && (notCur || hasFlag) )
- list << ' ';
- if (hasFlag)
- list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' ';
- if ( notCur || hasFlag )
- list << (*iu)->nameStartString() << (*iu)->getName();
- }
- list << ')';
- return list.str();
- }
- }
-
- // wasn't found in xor list
- if (!a->getFlag().empty()) {
- list << "(" << a->flagStartChar() << a->getFlag() << ' ' <<
- a->nameStartString() << a->getName() << ')';
- }
-
- return list.str();
-}
-
-} //namespace TCLAP
-#endif
+++ /dev/null
-// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
-
-/******************************************************************************
- *
- * file: sstream.h
- *
- * Copyright (c) 2003, Michael E. Smoot .
- * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno .
- * Copyright (c) 2017 Google Inc.
- * All rights reserved.
- *
- * See the file COPYING in the top directory of this distribution for
- * more information.
- *
- * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- *****************************************************************************/
-
-#ifndef TCLAP_SSTREAM_H
-#define TCLAP_SSTREAM_H
-
-#if !defined(HAVE_STRSTREAM)
-// Assume sstream is available if strstream is not specified
-// (https://sourceforge.net/p/tclap/bugs/23/)
-#define HAVE_SSTREAM
-#endif
-
-#if defined(HAVE_SSTREAM)
-#include <sstream>
-namespace TCLAP {
- typedef std::istringstream istringstream;
- typedef std::ostringstream ostringstream;
-}
-#elif defined(HAVE_STRSTREAM)
-#include <strstream>
-namespace TCLAP {
- typedef std::istrstream istringstream;
- typedef std::ostrstream ostringstream;
-}
-#else
-#error "Need a stringstream (sstream or strstream) to compile!"
-#endif
-
-#endif // TCLAP_SSTREAM_H